Add Filtering, HealthCheck, Better Tests (#350)
feat: add filtering when choosing merge requests (#346) feat: Add healthcheck (#345) refactor: Move to gomock (#349) feat: Makes the remote of the plugin configurable (#348) This is a #MINOR release.
This commit is contained in:
committed by
GitHub
parent
aa5d3c1f52
commit
4ae623cd65
7
.github/CONTRIBUTING.md
vendored
7
.github/CONTRIBUTING.md
vendored
@@ -38,6 +38,13 @@ $ go fmt ./...
|
|||||||
$ golangci-lint run
|
$ golangci-lint run
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you are writing tests and have added something to the Go client, you can re-generate the mocked client like so:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ go install go.uber.org/mock/mockgen@latest # Install the mockgen CLI on your machine
|
||||||
|
$ mockgen -source cmd/types.go > cmd/mocks/fake_client.go
|
||||||
|
```
|
||||||
|
|
||||||
For changes to the Lua codebase: We use <a href="https://github.com/JohnnyMorganz/StyLua">stylua</a> for formatting and <a href="https://github.com/mpeterv/luacheck">luacheck</a> for linting. Run these commands in the root of the repository:
|
For changes to the Lua codebase: We use <a href="https://github.com/JohnnyMorganz/StyLua">stylua</a> for formatting and <a href="https://github.com/mpeterv/luacheck">luacheck</a> for linting. Run these commands in the root of the repository:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
2
.github/workflows/lua.yaml
vendored
2
.github/workflows/lua.yaml
vendored
@@ -46,7 +46,7 @@ jobs:
|
|||||||
- name: Install luajit
|
- name: Install luajit
|
||||||
uses: leafo/gh-actions-lua@v10
|
uses: leafo/gh-actions-lua@v10
|
||||||
with:
|
with:
|
||||||
luaVersion: "luajit-2.1.0-beta3"
|
luaVersion: "luajit-openresty"
|
||||||
- name: Install luarocks
|
- name: Install luarocks
|
||||||
uses: leafo/gh-actions-luarocks@v4
|
uses: leafo/gh-actions-luarocks@v4
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
|
|||||||
@@ -29,9 +29,6 @@ To view these help docs and to get more detailed help information, please run `:
|
|||||||
|
|
||||||
This will checkout the branch locally, and open the plugin's reviewer pane.
|
This will checkout the branch locally, and open the plugin's reviewer pane.
|
||||||
|
|
||||||
NOTE: At the moment, the plugin assumes that the remote where you want to merge your feature branch
|
|
||||||
is called "origin".
|
|
||||||
|
|
||||||
For more detailed information about the Lua APIs please run `:h gitlab.nvim.api`
|
For more detailed information about the Lua APIs please run `:h gitlab.nvim.api`
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* approveHandler approves a merge request. */
|
/* approveHandler approves a merge request. */
|
||||||
func (a *api) approveHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) approveHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
||||||
|
|||||||
@@ -1,52 +1,59 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
func approveMergeRequest(pid interface{}, mr int, opt *gitlab.ApproveMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequestApprovals, *gitlab.Response, error) {
|
|
||||||
return &gitlab.MergeRequestApprovals{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func approveMergeRequestNon200(pid interface{}, mr int, opt *gitlab.ApproveMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequestApprovals, *gitlab.Response, error) {
|
|
||||||
return &gitlab.MergeRequestApprovals{}, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func approveMergeRequestErr(pid interface{}, mr int, opt *gitlab.ApproveMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequestApprovals, *gitlab.Response, error) {
|
|
||||||
return &gitlab.MergeRequestApprovals{}, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApproveHandler(t *testing.T) {
|
func TestApproveHandler(t *testing.T) {
|
||||||
t.Run("Approves merge request", func(t *testing.T) {
|
t.Run("Approves merge request", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ApproveMergeRequest("", mock_main.MergeId, nil, nil).Return(&gitlab.MergeRequestApprovals{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/approve", nil)
|
request := makeRequest(t, http.MethodPost, "/mr/approve", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{approveMergeRequest: approveMergeRequest})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, SuccessResponse{})
|
data := serveRequest(t, server, request, SuccessResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Approved MR")
|
assert(t, data.Message, "Approved MR")
|
||||||
assert(t, data.Status, http.StatusOK)
|
assert(t, data.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-POST method", func(t *testing.T) {
|
t.Run("Disallows non-POST method", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ApproveMergeRequest("", mock_main.MergeId, nil, nil).Return(&gitlab.MergeRequestApprovals{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPut, "/mr/approve", nil)
|
request := makeRequest(t, http.MethodPut, "/mr/approve", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{approveMergeRequest: approveMergeRequest})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkBadMethod(t, *data, http.MethodPost)
|
checkBadMethod(t, *data, http.MethodPost)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ApproveMergeRequest("", mock_main.MergeId, nil, nil).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/approve", nil)
|
request := makeRequest(t, http.MethodPost, "/mr/approve", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{approveMergeRequest: approveMergeRequestErr})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not approve merge request")
|
checkErrorFromGitlab(t, *data, "Could not approve merge request")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ApproveMergeRequest("", mock_main.MergeId, nil, nil).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/approve", nil)
|
request := makeRequest(t, http.MethodPost, "/mr/approve", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{approveMergeRequest: approveMergeRequestNon200})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkNon200(t, *data, "Could not approve merge request", "/mr/approve")
|
checkNon200(t, *data, "Could not approve merge request", "/mr/approve")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type AssigneesRequestResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* assigneesHandler adds or removes assignees from a merge request. */
|
/* assigneesHandler adds or removes assignees from a merge request. */
|
||||||
func (a *api) assigneesHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) assigneesHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodPut {
|
if r.Method != http.MethodPut {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodPut)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPut)
|
||||||
|
|||||||
@@ -1,56 +1,67 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func updateAssignees(pid interface{}, mergeRequest int, opt *gitlab.UpdateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
var updatePayload = AssigneeUpdateRequest{Ids: []int{1, 2}}
|
||||||
return &gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateAssigneesNon200(pid interface{}, mergeRequest int, opt *gitlab.UpdateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateAssigneesErr(pid interface{}, mergeRequest int, opt *gitlab.UpdateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAssigneeHandler(t *testing.T) {
|
func TestAssigneeHandler(t *testing.T) {
|
||||||
t.Run("Updates assignees", func(t *testing.T) {
|
t.Run("Updates assignees", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPut, "/mr/assignee", AssigneeUpdateRequest{Ids: []int{1, 2}})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateMergeRequest: updateAssignees})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().UpdateMergeRequest("", mock_main.MergeId, gomock.Any()).Return(&gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPut, "/mr/assignee", updatePayload)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, AssigneeUpdateResponse{})
|
data := serveRequest(t, server, request, AssigneeUpdateResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Assignees updated")
|
assert(t, data.SuccessResponse.Message, "Assignees updated")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-PUT method", func(t *testing.T) {
|
t.Run("Disallows non-PUT method", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().UpdateMergeRequest("", mock_main.MergeId, gomock.Any()).Return(&gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/assignee", nil)
|
request := makeRequest(t, http.MethodPost, "/mr/assignee", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateMergeRequest: updateAssignees})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Status, http.StatusMethodNotAllowed)
|
assert(t, data.Status, http.StatusMethodNotAllowed)
|
||||||
assert(t, data.Details, "Invalid request type")
|
assert(t, data.Details, "Invalid request type")
|
||||||
assert(t, data.Message, "Expected PUT")
|
assert(t, data.Message, "Expected PUT")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPut, "/mr/assignee", AssigneeUpdateRequest{Ids: []int{1, 2}})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateMergeRequest: updateAssigneesErr})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().UpdateMergeRequest("", mock_main.MergeId, gomock.Any()).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPut, "/mr/assignee", updatePayload)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Status, http.StatusInternalServerError)
|
assert(t, data.Status, http.StatusInternalServerError)
|
||||||
assert(t, data.Message, "Could not modify merge request assignees")
|
assert(t, data.Message, "Could not modify merge request assignees")
|
||||||
assert(t, data.Details, "Some error from Gitlab")
|
assert(t, data.Details, "Some error from Gitlab")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPut, "/mr/assignee", AssigneeUpdateRequest{Ids: []int{1, 2}})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateMergeRequest: updateAssigneesNon200})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().UpdateMergeRequest("", mock_main.MergeId, gomock.Any()).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPut, "/mr/assignee", updatePayload)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Status, http.StatusSeeOther)
|
assert(t, data.Status, http.StatusSeeOther)
|
||||||
assert(t, data.Message, "Could not modify merge request assignees")
|
assert(t, data.Message, "Could not modify merge request assignees")
|
||||||
assert(t, data.Details, "An error occurred on the /mr/assignee endpoint")
|
assert(t, data.Details, "An error occurred on the /mr/assignee endpoint")
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func (ar attachmentReader) ReadFile(path string) (io.Reader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* attachmentHandler uploads an attachment (file, image, etc) to Gitlab and returns metadata about the upload. */
|
/* attachmentHandler uploads an attachment (file, image, etc) to Gitlab and returns metadata about the upload. */
|
||||||
func (a *api) attachmentHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) attachmentHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
||||||
|
|||||||
@@ -2,64 +2,67 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MockAttachmentReader struct{}
|
func withMockFileReader(a *Api) error {
|
||||||
|
reader := mock_main.MockAttachmentReader{}
|
||||||
func (mf MockAttachmentReader) ReadFile(path string) (io.Reader, error) {
|
|
||||||
return bytes.NewReader([]byte{}), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func uploadFile(pid interface{}, content io.Reader, filename string, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectFile, *gitlab.Response, error) {
|
|
||||||
return &gitlab.ProjectFile{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func uploadFileNon200(pid interface{}, content io.Reader, filename string, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectFile, *gitlab.Response, error) {
|
|
||||||
return &gitlab.ProjectFile{}, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func uploadFileErr(pid interface{}, content io.Reader, filename string, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectFile, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func withMockFileReader(a *api) error {
|
|
||||||
reader := MockAttachmentReader{}
|
|
||||||
a.fileReader = reader
|
a.fileReader = reader
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var reader = bytes.NewReader([]byte{})
|
||||||
|
var attachmentTestRequestData = AttachmentRequest{
|
||||||
|
FileName: "some_file_name",
|
||||||
|
FilePath: "some_file_path",
|
||||||
|
}
|
||||||
|
|
||||||
func TestAttachmentHandler(t *testing.T) {
|
func TestAttachmentHandler(t *testing.T) {
|
||||||
t.Run("Returns 200-status response after upload", func(t *testing.T) {
|
t.Run("Returns 200-status response after upload", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/attachment", AttachmentRequest{FilePath: "some_file_path", FileName: "some_file_name"})
|
client := mock_main.NewMockClient(t)
|
||||||
router, _ := createRouterAndApi(fakeClient{uploadFile: uploadFile}, withMockFileReader)
|
client.EXPECT().UploadFile("", reader, attachmentTestRequestData.FileName).Return(&gitlab.ProjectFile{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/attachment", attachmentTestRequestData)
|
||||||
|
router, _ := CreateRouterAndApi(client, withMockFileReader)
|
||||||
data := serveRequest(t, router, request, AttachmentResponse{})
|
data := serveRequest(t, router, request, AttachmentResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
assert(t, data.SuccessResponse.Message, "File uploaded successfully")
|
assert(t, data.SuccessResponse.Message, "File uploaded successfully")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-POST method", func(t *testing.T) {
|
t.Run("Disallows non-POST method", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPut, "/attachment", AttachmentRequest{FilePath: "some_file_path", FileName: "some_file_name"})
|
client := mock_main.NewMockClient(t)
|
||||||
router, _ := createRouterAndApi(fakeClient{uploadFile: uploadFile}, withMockFileReader)
|
client.EXPECT().UploadFile("", reader, attachmentTestRequestData.FileName).Return(&gitlab.ProjectFile{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPut, "/attachment", attachmentTestRequestData)
|
||||||
|
router, _ := CreateRouterAndApi(client, withMockFileReader)
|
||||||
data := serveRequest(t, router, request, ErrorResponse{})
|
data := serveRequest(t, router, request, ErrorResponse{})
|
||||||
|
|
||||||
checkBadMethod(t, *data, http.MethodPost)
|
checkBadMethod(t, *data, http.MethodPost)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/attachment", AttachmentRequest{FilePath: "some_file_path", FileName: "some_file_name"})
|
client := mock_main.NewMockClient(t)
|
||||||
router, _ := createRouterAndApi(fakeClient{uploadFile: uploadFileErr}, withMockFileReader)
|
client.EXPECT().UploadFile("", reader, attachmentTestRequestData.FileName).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/attachment", attachmentTestRequestData)
|
||||||
|
router, _ := CreateRouterAndApi(client, withMockFileReader)
|
||||||
|
|
||||||
data := serveRequest(t, router, request, ErrorResponse{})
|
data := serveRequest(t, router, request, ErrorResponse{})
|
||||||
checkErrorFromGitlab(t, *data, "Could not upload some_file_name to Gitlab")
|
checkErrorFromGitlab(t, *data, "Could not upload some_file_name to Gitlab")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/attachment", AttachmentRequest{FilePath: "some_file_path", FileName: "some_file_name"})
|
client := mock_main.NewMockClient(t)
|
||||||
router, _ := createRouterAndApi(fakeClient{uploadFile: uploadFileNon200}, withMockFileReader)
|
client.EXPECT().UploadFile("", reader, attachmentTestRequestData.FileName).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/attachment", attachmentTestRequestData)
|
||||||
|
router, _ := CreateRouterAndApi(client, withMockFileReader)
|
||||||
|
|
||||||
data := serveRequest(t, router, request, ErrorResponse{})
|
data := serveRequest(t, router, request, ErrorResponse{})
|
||||||
checkNon200(t, *data, "Could not upload some_file_name to Gitlab", "/attachment")
|
checkNon200(t, *data, "Could not upload some_file_name to Gitlab", "/attachment")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,15 +14,6 @@ import (
|
|||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DebugSettings struct {
|
|
||||||
GoRequest bool `json:"go_request"`
|
|
||||||
GoResponse bool `json:"go_response"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConnectionOptions struct {
|
|
||||||
Insecure bool `json:"insecure"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProjectInfo struct {
|
type ProjectInfo struct {
|
||||||
ProjectId string
|
ProjectId string
|
||||||
MergeId int
|
MergeId int
|
||||||
@@ -46,53 +37,27 @@ type Client struct {
|
|||||||
/* initGitlabClient parses and validates the project settings and initializes the Gitlab client. */
|
/* initGitlabClient parses and validates the project settings and initializes the Gitlab client. */
|
||||||
func initGitlabClient() (error, *Client) {
|
func initGitlabClient() (error, *Client) {
|
||||||
|
|
||||||
if len(os.Args) < 7 {
|
if pluginOptions.GitlabUrl == "" {
|
||||||
return errors.New("Must provide gitlab url, port, auth token, debug settings, log path, and connection settings"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
gitlabInstance := os.Args[1]
|
|
||||||
if gitlabInstance == "" {
|
|
||||||
return errors.New("GitLab instance URL cannot be empty"), nil
|
return errors.New("GitLab instance URL cannot be empty"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
authToken := os.Args[3]
|
var apiCustUrl = fmt.Sprintf(pluginOptions.GitlabUrl + "/api/v4")
|
||||||
if authToken == "" {
|
|
||||||
return errors.New("Auth token cannot be empty"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse debug settings and initialize logger handlers */
|
|
||||||
debugSettings := os.Args[4]
|
|
||||||
var debugObject DebugSettings
|
|
||||||
err := json.Unmarshal([]byte(debugSettings), &debugObject)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Could not parse debug settings: %w, %s", err, debugSettings), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse connection options */
|
|
||||||
connectionSettings := os.Args[6]
|
|
||||||
var connectionObject ConnectionOptions
|
|
||||||
err = json.Unmarshal([]byte(connectionSettings), &connectionObject)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Could not parse connection settings: %w, %s", err, connectionSettings), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var apiCustUrl = fmt.Sprintf(gitlabInstance + "/api/v4")
|
|
||||||
|
|
||||||
gitlabOptions := []gitlab.ClientOptionFunc{
|
gitlabOptions := []gitlab.ClientOptionFunc{
|
||||||
gitlab.WithBaseURL(apiCustUrl),
|
gitlab.WithBaseURL(apiCustUrl),
|
||||||
}
|
}
|
||||||
|
|
||||||
if debugObject.GoRequest {
|
if pluginOptions.Debug.Request {
|
||||||
gitlabOptions = append(gitlabOptions, gitlab.WithRequestLogHook(requestLogger))
|
gitlabOptions = append(gitlabOptions, gitlab.WithRequestLogHook(requestLogger))
|
||||||
}
|
}
|
||||||
|
|
||||||
if debugObject.GoResponse {
|
if pluginOptions.Debug.Response {
|
||||||
gitlabOptions = append(gitlabOptions, gitlab.WithResponseLogHook(responseLogger))
|
gitlabOptions = append(gitlabOptions, gitlab.WithResponseLogHook(responseLogger))
|
||||||
}
|
}
|
||||||
|
|
||||||
tr := &http.Transport{
|
tr := &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: &tls.Config{
|
||||||
InsecureSkipVerify: connectionObject.Insecure,
|
InsecureSkipVerify: pluginOptions.ConnectionSettings.Insecure,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +65,7 @@ func initGitlabClient() (error, *Client) {
|
|||||||
retryClient.HTTPClient.Transport = tr
|
retryClient.HTTPClient.Transport = tr
|
||||||
gitlabOptions = append(gitlabOptions, gitlab.WithHTTPClient(retryClient.HTTPClient))
|
gitlabOptions = append(gitlabOptions, gitlab.WithHTTPClient(retryClient.HTTPClient))
|
||||||
|
|
||||||
client, err := gitlab.NewClient(authToken, gitlabOptions...)
|
client, err := gitlab.NewClient(pluginOptions.AuthToken, gitlabOptions...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to create client: %v", err), nil
|
return fmt.Errorf("Failed to create client: %v", err), nil
|
||||||
@@ -130,12 +95,9 @@ func initProjectSettings(c *Client, gitInfo GitProjectInfo) (error, *ProjectInfo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(fmt.Sprintf("Error getting project at %s", gitInfo.RemoteUrl), err), nil
|
return fmt.Errorf(fmt.Sprintf("Error getting project at %s", gitInfo.RemoteUrl), err), nil
|
||||||
}
|
}
|
||||||
if project == nil {
|
|
||||||
return fmt.Errorf(fmt.Sprintf("Could not find project at %s", gitInfo.RemoteUrl), err), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if project == nil {
|
if project == nil {
|
||||||
return fmt.Errorf("No projects you are a member of contained remote URL %s", gitInfo.RemoteUrl), nil
|
return fmt.Errorf(fmt.Sprintf("Could not find project at %s", gitInfo.RemoteUrl), err), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
projectId := fmt.Sprint(project.ID)
|
projectId := fmt.Sprint(project.ID)
|
||||||
@@ -195,15 +157,14 @@ var responseLogger retryablehttp.ResponseLogHook = func(l retryablehttp.Logger,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func openLogFile() *os.File {
|
func openLogFile() *os.File {
|
||||||
logFile := os.Args[5]
|
file, err := os.OpenFile(pluginOptions.LogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
file, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Printf("Log file %s does not exist", logFile)
|
log.Printf("Log file %s does not exist", pluginOptions.LogPath)
|
||||||
} else if os.IsPermission(err) {
|
} else if os.IsPermission(err) {
|
||||||
log.Printf("Permission denied for log file %s", logFile)
|
log.Printf("Permission denied for log file %s", pluginOptions.LogPath)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Error opening log file %s: %v", logFile, err)
|
log.Printf("Error opening log file %s: %v", pluginOptions.LogPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func (comment CommentWithPosition) GetPositionData() PositionData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* commentHandler creates, edits, and deletes discussions (comments, multi-line comments) */
|
/* commentHandler creates, edits, and deletes discussions (comments, multi-line comments) */
|
||||||
func (a *api) commentHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) commentHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
@@ -58,7 +58,7 @@ func (a *api) commentHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* deleteComment deletes a note, multiline comment, or comment, which are all considered discussion notes. */
|
/* deleteComment deletes a note, multiline comment, or comment, which are all considered discussion notes. */
|
||||||
func (a *api) deleteComment(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) deleteComment(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
||||||
@@ -99,7 +99,7 @@ func (a *api) deleteComment(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* postComment creates a note, multiline comment, or comment. */
|
/* postComment creates a note, multiline comment, or comment. */
|
||||||
func (a *api) postComment(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) postComment(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
||||||
@@ -156,7 +156,7 @@ func (a *api) postComment(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* editComment changes the text of a comment or changes it's resolved status. */
|
/* editComment changes the text of a comment or changes it's resolved status. */
|
||||||
func (a *api) editComment(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) editComment(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -6,139 +6,176 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createMergeRequestDiscussion(pid interface{}, mergeRequest int, opt *gitlab.CreateMergeRequestDiscussionOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Discussion, *gitlab.Response, error) {
|
var testCommentCreationData = PostCommentRequest{
|
||||||
return &gitlab.Discussion{Notes: []*gitlab.Note{{}}}, makeResponse(http.StatusOK), nil
|
Comment: "Some comment",
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMergeRequestDiscussionNon200(pid interface{}, mergeRequest int, opt *gitlab.CreateMergeRequestDiscussionOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Discussion, *gitlab.Response, error) {
|
var testCommentDeletionData = DeleteCommentRequest{
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
NoteId: 3,
|
||||||
|
DiscussionId: "abc123",
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMergeRequestDiscussionErr(pid interface{}, mergeRequest int, opt *gitlab.CreateMergeRequestDiscussionOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Discussion, *gitlab.Response, error) {
|
var testEditCommentData = EditCommentRequest{
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
Comment: "Some comment",
|
||||||
|
NoteId: 3,
|
||||||
|
DiscussionId: "abc123",
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostComment(t *testing.T) {
|
func TestPostComment(t *testing.T) {
|
||||||
t.Run("Creates a new note (unlinked comment)", func(t *testing.T) {
|
t.Run("Creates a new note (unlinked comment)", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/comment", PostCommentRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMergeRequestDiscussion: createMergeRequestDiscussion})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().CreateMergeRequestDiscussion(
|
||||||
|
"",
|
||||||
|
mock_main.MergeId,
|
||||||
|
gomock.Any(),
|
||||||
|
).Return(&gitlab.Discussion{Notes: []*gitlab.Note{{}}}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/comment", testCommentCreationData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, CommentResponse{})
|
data := serveRequest(t, server, request, CommentResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Comment created successfully")
|
assert(t, data.SuccessResponse.Message, "Comment created successfully")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Creates a new comment", func(t *testing.T) {
|
t.Run("Creates a new comment", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/comment", PostCommentRequest{
|
// Re-create comment creation data to avoid mutating this variable in other tests
|
||||||
|
testCommentCreationData := PostCommentRequest{
|
||||||
|
Comment: "Some comment",
|
||||||
PositionData: PositionData{
|
PositionData: PositionData{
|
||||||
FileName: "some_file.txt",
|
FileName: "file.txt",
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
server, _ := createRouterAndApi(fakeClient{createMergeRequestDiscussion: createMergeRequestDiscussion})
|
|
||||||
data := serveRequest(t, server, request, CommentResponse{})
|
|
||||||
assert(t, data.SuccessResponse.Message, "Comment created successfully")
|
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Creates a new multiline comment", func(t *testing.T) {
|
client := mock_main.NewMockClient(t)
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/comment", PostCommentRequest{
|
mock_main.WithMr(t, client)
|
||||||
PositionData: PositionData{
|
client.EXPECT().CreateMergeRequestDiscussion(
|
||||||
FileName: "some_file.txt",
|
"",
|
||||||
LineRange: &LineRange{
|
mock_main.MergeId,
|
||||||
StartRange: &LinePosition{}, /* These would have real data */
|
gomock.Any(),
|
||||||
EndRange: &LinePosition{},
|
).Return(&gitlab.Discussion{Notes: []*gitlab.Note{{}}}, makeResponse(http.StatusOK), nil)
|
||||||
},
|
|
||||||
},
|
request := makeRequest(t, http.MethodPost, "/mr/comment", testCommentCreationData)
|
||||||
})
|
|
||||||
server, _ := createRouterAndApi(fakeClient{createMergeRequestDiscussion: createMergeRequestDiscussion})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, CommentResponse{})
|
data := serveRequest(t, server, request, CommentResponse{})
|
||||||
assert(t, data.SuccessResponse.Message, "Comment created successfully")
|
assert(t, data.SuccessResponse.Message, "Comment created successfully")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/comment", PostCommentRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMergeRequestDiscussion: createMergeRequestDiscussionErr})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().CreateMergeRequestDiscussion(
|
||||||
|
"",
|
||||||
|
mock_main.MergeId,
|
||||||
|
gomock.Any(),
|
||||||
|
).Return(nil, nil, errors.New("Some error from Gitlab"))
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/comment", testCommentCreationData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not create discussion")
|
checkErrorFromGitlab(t, *data, "Could not create discussion")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/comment", PostCommentRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMergeRequestDiscussion: createMergeRequestDiscussionNon200})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().CreateMergeRequestDiscussion(
|
||||||
|
"",
|
||||||
|
mock_main.MergeId,
|
||||||
|
gomock.Any(),
|
||||||
|
).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/comment", testCommentCreationData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkNon200(t, *data, "Could not create discussion", "/mr/comment")
|
checkNon200(t, *data, "Could not create discussion", "/mr/comment")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteMergeRequestDiscussionNote(pid interface{}, mergeRequest int, discussion string, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteMergeRequestDiscussionNoteErr(pid interface{}, mergeRequest int, discussion string, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteMergeRequestDiscussionNoteNon200(pid interface{}, mergeRequest int, discussion string, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteComment(t *testing.T) {
|
func TestDeleteComment(t *testing.T) {
|
||||||
t.Run("Deletes a comment", func(t *testing.T) {
|
t.Run("Deletes a comment", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodDelete, "/mr/comment", DeleteCommentRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{deleteMergeRequestDiscussionNote: deleteMergeRequestDiscussionNote})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().DeleteMergeRequestDiscussionNote("", mock_main.MergeId, testCommentDeletionData.DiscussionId, testCommentDeletionData.NoteId).Return(makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodDelete, "/mr/comment", testCommentDeletionData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, CommentResponse{})
|
data := serveRequest(t, server, request, CommentResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Comment deleted successfully")
|
assert(t, data.SuccessResponse.Message, "Comment deleted successfully")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodDelete, "/mr/comment", DeleteCommentRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{deleteMergeRequestDiscussionNote: deleteMergeRequestDiscussionNoteErr})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().DeleteMergeRequestDiscussionNote("", mock_main.MergeId, testCommentDeletionData.DiscussionId, testCommentDeletionData.NoteId).Return(nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodDelete, "/mr/comment", testCommentDeletionData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not delete comment")
|
checkErrorFromGitlab(t, *data, "Could not delete comment")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodDelete, "/mr/comment", DeleteCommentRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{deleteMergeRequestDiscussionNote: deleteMergeRequestDiscussionNoteNon200})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().DeleteMergeRequestDiscussionNote("", mock_main.MergeId, testCommentDeletionData.DiscussionId, testCommentDeletionData.NoteId).Return(makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodDelete, "/mr/comment", testCommentDeletionData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkNon200(t, *data, "Could not delete comment", "/mr/comment")
|
checkNon200(t, *data, "Could not delete comment", "/mr/comment")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateMergeRequestDiscussionNote(pid interface{}, mergeRequest int, discussion string, note int, opt *gitlab.UpdateMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
|
||||||
return &gitlab.Note{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateMergeRequestDiscussionNoteErr(pid interface{}, mergeRequest int, discussion string, note int, opt *gitlab.UpdateMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateMergeRequestDiscussionNoteNon200(pid interface{}, mergeRequest int, discussion string, note int, opt *gitlab.UpdateMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEditComment(t *testing.T) {
|
func TestEditComment(t *testing.T) {
|
||||||
t.Run("Edits a comment", func(t *testing.T) {
|
t.Run("Edits a comment", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPatch, "/mr/comment", EditCommentRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateMergeRequestDiscussionNote: updateMergeRequestDiscussionNote})
|
mock_main.WithMr(t, client)
|
||||||
|
opts := gitlab.UpdateMergeRequestDiscussionNoteOptions{
|
||||||
|
Body: gitlab.Ptr(testEditCommentData.Comment),
|
||||||
|
}
|
||||||
|
client.EXPECT().UpdateMergeRequestDiscussionNote("", mock_main.MergeId, testEditCommentData.DiscussionId, testEditCommentData.NoteId, &opts).Return(&gitlab.Note{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPatch, "/mr/comment", testEditCommentData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, CommentResponse{})
|
data := serveRequest(t, server, request, CommentResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Comment updated successfully")
|
assert(t, data.SuccessResponse.Message, "Comment updated successfully")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPatch, "/mr/comment", EditCommentRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateMergeRequestDiscussionNote: updateMergeRequestDiscussionNoteErr})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().UpdateMergeRequestDiscussionNote("", mock_main.MergeId, testEditCommentData.DiscussionId, testEditCommentData.NoteId, gomock.Any()).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPatch, "/mr/comment", testEditCommentData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not update comment")
|
checkErrorFromGitlab(t, *data, "Could not update comment")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPatch, "/mr/comment", EditCommentRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateMergeRequestDiscussionNote: updateMergeRequestDiscussionNoteNon200})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().UpdateMergeRequestDiscussionNote("", mock_main.MergeId, testEditCommentData.DiscussionId, testEditCommentData.NoteId, gomock.Any()).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPatch, "/mr/comment", testEditCommentData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkNon200(t, *data, "Could not update comment", "/mr/comment")
|
checkNon200(t, *data, "Could not update comment", "/mr/comment")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ type CreateMrRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* createMr creates a merge request */
|
/* createMr creates a merge request */
|
||||||
func (a *api) createMr(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) createMr(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
|
|||||||
@@ -1,29 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createMrFn(pid interface{}, opt *gitlab.CreateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
var testCreateMrRequestData = CreateMrRequest{
|
||||||
return &gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createMrFnErr(pid interface{}, opt *gitlab.CreateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func createMrFnNon200(pid interface{}, opt *gitlab.CreateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreateMr(t *testing.T) {
|
|
||||||
t.Run("Creates an MR", func(t *testing.T) {
|
|
||||||
|
|
||||||
body := CreateMrRequest{
|
|
||||||
Title: "Some title",
|
Title: "Some title",
|
||||||
Description: "Some description",
|
Description: "Some description",
|
||||||
TargetBranch: "main",
|
TargetBranch: "main",
|
||||||
@@ -31,75 +17,81 @@ func TestCreateMr(t *testing.T) {
|
|||||||
Squash: false,
|
Squash: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
func TestCreateMr(t *testing.T) {
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFn})
|
t.Run("Creates an MR", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().CreateMergeRequest("", gomock.Any()).Return(&gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/create_mr", testCreateMrRequestData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, SuccessResponse{})
|
data := serveRequest(t, server, request, SuccessResponse{})
|
||||||
assert(t, data.Message, "MR 'Some title' created")
|
assert(t, data.Message, "MR 'Some title' created")
|
||||||
assert(t, data.Status, http.StatusOK)
|
assert(t, data.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-POST methods", func(t *testing.T) {
|
t.Run("Disallows non-POST methods", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodGet, "/create_mr", CreateMrRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFn})
|
client.EXPECT().CreateMergeRequest("", gomock.Any()).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPatch, "/create_mr", testCreateMrRequestData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkBadMethod(t, *data, http.MethodPost)
|
checkBadMethod(t, *data, http.MethodPost)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
body := CreateMrRequest{
|
client := mock_main.NewMockClient(t)
|
||||||
Title: "Some title",
|
client.EXPECT().CreateMergeRequest("", gomock.Any()).Return(nil, nil, errorFromGitlab)
|
||||||
Description: "Some description",
|
|
||||||
TargetBranch: "main",
|
request := makeRequest(t, http.MethodPost, "/create_mr", testCreateMrRequestData)
|
||||||
DeleteBranch: false,
|
server, _ := CreateRouterAndApi(client)
|
||||||
Squash: false,
|
|
||||||
}
|
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFnErr})
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not create MR")
|
checkErrorFromGitlab(t, *data, "Could not create MR")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
body := CreateMrRequest{
|
client := mock_main.NewMockClient(t)
|
||||||
Title: "Some title",
|
client.EXPECT().CreateMergeRequest("", gomock.Any()).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
Description: "Some description",
|
|
||||||
TargetBranch: "main",
|
request := makeRequest(t, http.MethodPost, "/create_mr", testCreateMrRequestData)
|
||||||
DeleteBranch: false,
|
server, _ := CreateRouterAndApi(client)
|
||||||
Squash: false,
|
|
||||||
}
|
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFnNon200})
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkNon200(t, *data, "Could not create MR", "/create_mr")
|
checkNon200(t, *data, "Could not create MR", "/create_mr")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles missing titles", func(t *testing.T) {
|
t.Run("Handles missing titles", func(t *testing.T) {
|
||||||
body := CreateMrRequest{
|
client := mock_main.NewMockClient(t)
|
||||||
Title: "",
|
|
||||||
Description: "Some description",
|
missingTitleRequest := testCreateMrRequestData
|
||||||
TargetBranch: "main",
|
missingTitleRequest.Title = ""
|
||||||
DeleteBranch: false,
|
|
||||||
Squash: false,
|
client.EXPECT().CreateMergeRequest("", gomock.Any()).Return(&gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil)
|
||||||
}
|
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
request := makeRequest(t, http.MethodPost, "/create_mr", missingTitleRequest)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFn})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Status, http.StatusBadRequest)
|
assert(t, data.Status, http.StatusBadRequest)
|
||||||
assert(t, data.Message, "Could not create MR")
|
assert(t, data.Message, "Could not create MR")
|
||||||
assert(t, data.Details, "Title cannot be empty")
|
assert(t, data.Details, "Title cannot be empty")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles missing target branch", func(t *testing.T) {
|
t.Run("Handles missing target branch", func(t *testing.T) {
|
||||||
body := CreateMrRequest{
|
client := mock_main.NewMockClient(t)
|
||||||
Title: "Some title",
|
|
||||||
Description: "Some description",
|
missingTitleRequest := testCreateMrRequestData
|
||||||
TargetBranch: "",
|
missingTitleRequest.TargetBranch = ""
|
||||||
DeleteBranch: false,
|
|
||||||
Squash: false,
|
client.EXPECT().CreateMergeRequest("", gomock.Any()).Return(&gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil)
|
||||||
}
|
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
request := makeRequest(t, http.MethodPost, "/create_mr", missingTitleRequest)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFn})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Status, http.StatusBadRequest)
|
assert(t, data.Status, http.StatusBadRequest)
|
||||||
assert(t, data.Message, "Could not create MR")
|
assert(t, data.Message, "Could not create MR")
|
||||||
assert(t, data.Details, "Target branch cannot be empty")
|
assert(t, data.Details, "Target branch cannot be empty")
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func (draftNote DraftNoteWithPosition) GetPositionData() PositionData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* draftNoteHandler creates, edits, and deletes draft notes */
|
/* draftNoteHandler creates, edits, and deletes draft notes */
|
||||||
func (a *api) draftNoteHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) draftNoteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
@@ -69,7 +69,7 @@ func (a *api) draftNoteHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *api) draftNotePublisher(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) draftNotePublisher(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
||||||
@@ -126,7 +126,7 @@ func (a *api) draftNotePublisher(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* postDraftNote creates a draft note */
|
/* postDraftNote creates a draft note */
|
||||||
func (a *api) postDraftNote(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) postDraftNote(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
||||||
@@ -184,7 +184,7 @@ func (a *api) postDraftNote(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* deleteDraftNote deletes a draft note */
|
/* deleteDraftNote deletes a draft note */
|
||||||
func (a *api) deleteDraftNote(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) deleteDraftNote(w http.ResponseWriter, r *http.Request) {
|
||||||
suffix := strings.TrimPrefix(r.URL.Path, "/mr/draft_notes/")
|
suffix := strings.TrimPrefix(r.URL.Path, "/mr/draft_notes/")
|
||||||
id, err := strconv.Atoi(suffix)
|
id, err := strconv.Atoi(suffix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -217,7 +217,7 @@ func (a *api) deleteDraftNote(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* updateDraftNote edits the text of a draft comment */
|
/* updateDraftNote edits the text of a draft comment */
|
||||||
func (a *api) updateDraftNote(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) updateDraftNote(w http.ResponseWriter, r *http.Request) {
|
||||||
suffix := strings.TrimPrefix(r.URL.Path, "/mr/draft_notes/")
|
suffix := strings.TrimPrefix(r.URL.Path, "/mr/draft_notes/")
|
||||||
id, err := strconv.Atoi(suffix)
|
id, err := strconv.Atoi(suffix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -278,7 +278,7 @@ func (a *api) updateDraftNote(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* listDraftNotes lists all draft notes for the currently authenticated user */
|
/* listDraftNotes lists all draft notes for the currently authenticated user */
|
||||||
func (a *api) listDraftNotes(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) listDraftNotes(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
|
||||||
opt := gitlab.ListDraftNotesOptions{}
|
opt := gitlab.ListDraftNotesOptions{}
|
||||||
draftNotes, res, err := a.client.ListDraftNotes(a.projectInfo.ProjectId, a.projectInfo.MergeId, &opt)
|
draftNotes, res, err := a.client.ListDraftNotes(a.projectInfo.ProjectId, a.projectInfo.MergeId, &opt)
|
||||||
|
|||||||
@@ -1,25 +1,36 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func listDraftNotes(pid interface{}, mergeRequest int, opt *gitlab.ListDraftNotesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.DraftNote, *gitlab.Response, error) {
|
var testPostDraftNoteRequestData = PostDraftNoteRequest{
|
||||||
return []*gitlab.DraftNote{}, makeResponse(http.StatusOK), nil
|
Comment: "Some comment",
|
||||||
}
|
}
|
||||||
|
|
||||||
func listDraftNotesErr(pid interface{}, mergeRequest int, opt *gitlab.ListDraftNotesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.DraftNote, *gitlab.Response, error) {
|
var testUpdateDraftNoteRequest = UpdateDraftNoteRequest{
|
||||||
return nil, makeResponse(http.StatusInternalServerError), errors.New("Some error")
|
Note: "Some new note",
|
||||||
|
}
|
||||||
|
|
||||||
|
var testDraftNotePublishRequest = DraftNotePublishRequest{
|
||||||
|
Note: 3,
|
||||||
|
PublishAll: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListDraftNotes(t *testing.T) {
|
func TestListDraftNotes(t *testing.T) {
|
||||||
t.Run("Lists all draft notes", func(t *testing.T) {
|
t.Run("Lists all draft notes", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListDraftNotes("", mock_main.MergeId, gomock.Any()).Return([]*gitlab.DraftNote{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/mr/draft_notes/", nil)
|
request := makeRequest(t, http.MethodGet, "/mr/draft_notes/", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{listDraftNotes: listDraftNotes})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ListDraftNotesResponse{})
|
data := serveRequest(t, server, request, ListDraftNotesResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Draft notes fetched successfully")
|
assert(t, data.SuccessResponse.Message, "Draft notes fetched successfully")
|
||||||
@@ -27,29 +38,28 @@ func TestListDraftNotes(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles error", func(t *testing.T) {
|
t.Run("Handles error", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListDraftNotes("", mock_main.MergeId, gomock.Any()).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/mr/draft_notes/", nil)
|
request := makeRequest(t, http.MethodGet, "/mr/draft_notes/", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{listDraftNotes: listDraftNotesErr})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Could not get draft notes")
|
assert(t, data.Message, "Could not get draft notes")
|
||||||
assert(t, data.Status, http.StatusInternalServerError)
|
assert(t, data.Status, http.StatusInternalServerError)
|
||||||
assert(t, data.Details, "Some error")
|
assert(t, data.Details, errorFromGitlab.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createDraftNote(pid interface{}, mergeRequestIID int, opt *gitlab.CreateDraftNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.DraftNote, *gitlab.Response, error) {
|
|
||||||
return &gitlab.DraftNote{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createDraftNoteErr(pid interface{}, mergeRequestIID int, opt *gitlab.CreateDraftNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.DraftNote, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusInternalServerError), errors.New("Some error")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPostDraftNote(t *testing.T) {
|
func TestPostDraftNote(t *testing.T) {
|
||||||
t.Run("Posts new draft note", func(t *testing.T) {
|
t.Run("Posts new draft note", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/", PostDraftNoteRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{createDraftNote: createDraftNote})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().CreateDraftNote("", mock_main.MergeId, gomock.Any()).Return(&gitlab.DraftNote{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/", testPostDraftNoteRequestData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, DraftNoteResponse{})
|
data := serveRequest(t, server, request, DraftNoteResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Draft note created successfully")
|
assert(t, data.SuccessResponse.Message, "Draft note created successfully")
|
||||||
@@ -57,139 +67,179 @@ func TestPostDraftNote(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors on draft note creation", func(t *testing.T) {
|
t.Run("Handles errors on draft note creation", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/", PostDraftNoteRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{createDraftNote: createDraftNoteErr})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().CreateDraftNote("", mock_main.MergeId, gomock.Any()).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/", testPostDraftNoteRequestData)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Could not create draft note")
|
assert(t, data.Message, "Could not create draft note")
|
||||||
assert(t, data.Status, http.StatusInternalServerError)
|
assert(t, data.Status, http.StatusInternalServerError)
|
||||||
assert(t, data.Details, "Some error")
|
assert(t, data.Details, errorFromGitlab.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteDraftNote(pid interface{}, mergeRequest int, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteDraftNoteErr(pid interface{}, mergeRequest int, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return makeResponse(http.StatusInternalServerError), errors.New("Something went wrong")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteDraftNote(t *testing.T) {
|
func TestDeleteDraftNote(t *testing.T) {
|
||||||
t.Run("Deletes draft note", func(t *testing.T) {
|
t.Run("Deletes draft note", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodDelete, "/mr/draft_notes/3", nil)
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{deleteDraftNote: deleteDraftNote})
|
mock_main.WithMr(t, client)
|
||||||
data := serveRequest(t, server, request, SuccessResponse{})
|
urlId := 10
|
||||||
assert(t, data.Message, "Draft note deleted")
|
client.EXPECT().DeleteDraftNote("", mock_main.MergeId, urlId).Return(makeResponse(http.StatusOK), nil)
|
||||||
assert(t, data.Status, http.StatusOK)
|
|
||||||
|
request := makeRequest(t, http.MethodDelete, fmt.Sprintf("/mr/draft_notes/%d", urlId), nil)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
data := serveRequest(t, server, request, DraftNoteResponse{})
|
||||||
|
|
||||||
|
assert(t, data.SuccessResponse.Message, "Draft note deleted")
|
||||||
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles error", func(t *testing.T) {
|
t.Run("Handles error", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodDelete, "/mr/draft_notes/3", nil)
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{deleteDraftNote: deleteDraftNoteErr})
|
mock_main.WithMr(t, client)
|
||||||
|
urlId := 10
|
||||||
|
client.EXPECT().DeleteDraftNote("", mock_main.MergeId, urlId).Return(nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodDelete, fmt.Sprintf("/mr/draft_notes/%d", urlId), nil)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Could not delete draft note")
|
assert(t, data.Message, "Could not delete draft note")
|
||||||
assert(t, data.Status, http.StatusInternalServerError)
|
assert(t, data.Status, http.StatusInternalServerError)
|
||||||
|
assert(t, data.Details, errorFromGitlab.Error())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles bad ID", func(t *testing.T) {
|
t.Run("Handles bad ID", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodDelete, "/mr/draft_notes/abc", nil)
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{deleteDraftNote: deleteDraftNote})
|
mock_main.WithMr(t, client)
|
||||||
|
urlId := "abc"
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodDelete, fmt.Sprintf("/mr/draft_notes/%s", urlId), nil)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Could not parse draft note ID")
|
assert(t, data.Message, "Could not parse draft note ID")
|
||||||
assert(t, data.Status, http.StatusBadRequest)
|
assert(t, data.Status, http.StatusBadRequest)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateDraftNote(pid interface{}, mergeRequest int, note int, opt *gitlab.UpdateDraftNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.DraftNote, *gitlab.Response, error) {
|
|
||||||
return &gitlab.DraftNote{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEditDraftNote(t *testing.T) {
|
func TestEditDraftNote(t *testing.T) {
|
||||||
t.Run("Edits draft note", func(t *testing.T) {
|
t.Run("Edits draft note", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPatch, "/mr/draft_notes/3", UpdateDraftNoteRequest{Note: "Some new note", Position: gitlab.PositionOptions{}})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateDraftNote: updateDraftNote})
|
mock_main.WithMr(t, client)
|
||||||
data := serveRequest(t, server, request, SuccessResponse{})
|
urlId := 10
|
||||||
|
client.EXPECT().UpdateDraftNote("", mock_main.MergeId, urlId, gomock.Any()).Return(&gitlab.DraftNote{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPatch, fmt.Sprintf("/mr/draft_notes/%d", urlId), testUpdateDraftNoteRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
data := serveRequest(t, server, request, DraftNoteResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Draft note updated")
|
assert(t, data.Message, "Draft note updated")
|
||||||
assert(t, data.Status, http.StatusOK)
|
assert(t, data.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles bad ID", func(t *testing.T) {
|
t.Run("Handles bad ID", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPatch, "/mr/draft_notes/abc", nil)
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateDraftNote: updateDraftNote})
|
mock_main.WithMr(t, client)
|
||||||
|
urlId := "abc"
|
||||||
|
client.EXPECT().UpdateDraftNote("", mock_main.MergeId, urlId, gomock.Any()).Return(&gitlab.DraftNote{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPatch, fmt.Sprintf("/mr/draft_notes/%s", urlId), testUpdateDraftNoteRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Could not parse draft note ID")
|
assert(t, data.Message, "Could not parse draft note ID")
|
||||||
assert(t, data.Status, http.StatusBadRequest)
|
assert(t, data.Status, http.StatusBadRequest)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles empty note", func(t *testing.T) {
|
t.Run("Handles empty note", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPatch, "/mr/draft_notes/3", UpdateDraftNoteRequest{Note: ""})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{updateDraftNote: updateDraftNote})
|
mock_main.WithMr(t, client)
|
||||||
|
urlId := 10
|
||||||
|
|
||||||
|
testEmptyUpdateDraftNoteRequest := testUpdateDraftNoteRequest
|
||||||
|
testEmptyUpdateDraftNoteRequest.Note = ""
|
||||||
|
|
||||||
|
client.EXPECT().UpdateDraftNote("", mock_main.MergeId, urlId, gomock.Any()).Return(&gitlab.DraftNote{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPatch, fmt.Sprintf("/mr/draft_notes/%d", urlId), testEmptyUpdateDraftNoteRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Must provide draft note text")
|
assert(t, data.Message, "Must provide draft note text")
|
||||||
assert(t, data.Status, http.StatusBadRequest)
|
assert(t, data.Status, http.StatusBadRequest)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func publishDraftNote(pid interface{}, mergeRequest int, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func publishDraftNoteErr(pid interface{}, mergeRequest int, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return nil, errors.New("Some error")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPublishDraftNote(t *testing.T) {
|
func TestPublishDraftNote(t *testing.T) {
|
||||||
t.Run("Should publish a draft note", func(t *testing.T) {
|
t.Run("Should publish a draft note", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", DraftNotePublishRequest{Note: 3, PublishAll: false})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
mock_main.WithMr(t, client)
|
||||||
publishDraftNote: publishDraftNote,
|
client.EXPECT().PublishDraftNote("", mock_main.MergeId, testDraftNotePublishRequest.Note).Return(makeResponse(http.StatusOK), nil)
|
||||||
})
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", testDraftNotePublishRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, SuccessResponse{})
|
data := serveRequest(t, server, request, SuccessResponse{})
|
||||||
assert(t, data.Message, "Draft note(s) published")
|
assert(t, data.Message, "Draft note(s) published")
|
||||||
assert(t, data.Status, http.StatusOK)
|
assert(t, data.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles bad/missing ID", func(t *testing.T) {
|
t.Run("Handles bad/missing ID", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", DraftNotePublishRequest{PublishAll: false})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{publishDraftNote: publishDraftNote})
|
mock_main.WithMr(t, client)
|
||||||
|
|
||||||
|
// Missing Note ID
|
||||||
|
testDraftNotePublishRequest := DraftNotePublishRequest{
|
||||||
|
PublishAll: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", testDraftNotePublishRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
assert(t, data.Message, "Must provide Note ID")
|
assert(t, data.Message, "Must provide Note ID")
|
||||||
assert(t, data.Status, http.StatusBadRequest)
|
assert(t, data.Status, http.StatusBadRequest)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles error", func(t *testing.T) {
|
t.Run("Handles error", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", DraftNotePublishRequest{PublishAll: false, Note: 3})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{publishDraftNote: publishDraftNoteErr})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().PublishDraftNote("", mock_main.MergeId, testDraftNotePublishRequest.Note).Return(nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", testDraftNotePublishRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Could not publish draft note(s)")
|
assert(t, data.Message, "Could not publish draft note(s)")
|
||||||
assert(t, data.Status, http.StatusInternalServerError)
|
assert(t, data.Status, http.StatusInternalServerError)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func publishAllDraftNotes(pid interface{}, mergeRequest int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func publishAllDraftNotesErr(pid interface{}, mergeRequest int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return nil, errors.New("Some error")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPublishAllDraftNotes(t *testing.T) {
|
func TestPublishAllDraftNotes(t *testing.T) {
|
||||||
t.Run("Should publish all draft notes", func(t *testing.T) {
|
t.Run("Should publish all draft notes", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().PublishAllDraftNotes("", mock_main.MergeId).Return(makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", DraftNotePublishRequest{PublishAll: true})
|
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", DraftNotePublishRequest{PublishAll: true})
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
server, _ := CreateRouterAndApi(client)
|
||||||
publishAllDraftNotes: publishAllDraftNotes,
|
|
||||||
})
|
|
||||||
data := serveRequest(t, server, request, SuccessResponse{})
|
data := serveRequest(t, server, request, SuccessResponse{})
|
||||||
assert(t, data.Message, "Draft note(s) published")
|
assert(t, data.Message, "Draft note(s) published")
|
||||||
assert(t, data.Status, http.StatusOK)
|
assert(t, data.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should handle an error", func(t *testing.T) {
|
t.Run("Should handle an error", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().PublishAllDraftNotes("", mock_main.MergeId).Return(nil, errorFromGitlab)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", DraftNotePublishRequest{PublishAll: true})
|
request := makeRequest(t, http.MethodPost, "/mr/draft_notes/publish", DraftNotePublishRequest{PublishAll: true})
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
server, _ := CreateRouterAndApi(client)
|
||||||
publishAllDraftNotes: publishAllDraftNotesErr,
|
|
||||||
})
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
assert(t, data.Message, "Could not publish draft note(s)")
|
assert(t, data.Message, "Could not publish draft note(s)")
|
||||||
assert(t, data.Status, http.StatusInternalServerError)
|
assert(t, data.Status, http.StatusInternalServerError)
|
||||||
|
|||||||
10
cmd/emoji.go
10
cmd/emoji.go
@@ -43,7 +43,7 @@ type CreateEmojiResponse struct {
|
|||||||
attachEmojisToApi reads the emojis from our external JSON file
|
attachEmojisToApi reads the emojis from our external JSON file
|
||||||
and attaches them to the API so that they can be looked up later
|
and attaches them to the API so that they can be looked up later
|
||||||
*/
|
*/
|
||||||
func attachEmojisToApi(a *api) error {
|
func attachEmojisToApi(a *Api) error {
|
||||||
|
|
||||||
e, err := os.Executable()
|
e, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -78,7 +78,7 @@ func attachEmojisToApi(a *api) error {
|
|||||||
Fetches emojis for a set of notes and comments in parallel and returns a map of note IDs to their emojis.
|
Fetches emojis for a set of notes and comments in parallel and returns a map of note IDs to their emojis.
|
||||||
Gitlab's API does not allow for fetching notes for an entire discussion thread so we have to do it per-note.
|
Gitlab's API does not allow for fetching notes for an entire discussion thread so we have to do it per-note.
|
||||||
*/
|
*/
|
||||||
func (a *api) fetchEmojisForNotesAndComments(noteIDs []int) (map[int][]*gitlab.AwardEmoji, error) {
|
func (a *Api) fetchEmojisForNotesAndComments(noteIDs []int) (map[int][]*gitlab.AwardEmoji, error) {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
emojis := make(map[int][]*gitlab.AwardEmoji)
|
emojis := make(map[int][]*gitlab.AwardEmoji)
|
||||||
@@ -131,7 +131,7 @@ func (a *api) fetchEmojisForNotesAndComments(noteIDs []int) (map[int][]*gitlab.A
|
|||||||
return emojis, nil
|
return emojis, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *api) emojiNoteHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) emojiNoteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
@@ -145,7 +145,7 @@ func (a *api) emojiNoteHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* deleteEmojiFromNote deletes an emoji from a note based on the emoji (awardable) ID and the note's ID */
|
/* deleteEmojiFromNote deletes an emoji from a note based on the emoji (awardable) ID and the note's ID */
|
||||||
func (a *api) deleteEmojiFromNote(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) deleteEmojiFromNote(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
suffix := strings.TrimPrefix(r.URL.Path, "/mr/awardable/note/")
|
suffix := strings.TrimPrefix(r.URL.Path, "/mr/awardable/note/")
|
||||||
ids := strings.Split(suffix, "/")
|
ids := strings.Split(suffix, "/")
|
||||||
@@ -187,7 +187,7 @@ func (a *api) deleteEmojiFromNote(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* postEmojiOnNote adds an emojis to a note based on the note's ID */
|
/* postEmojiOnNote adds an emojis to a note based on the note's ID */
|
||||||
func (a *api) postEmojiOnNote(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) postEmojiOnNote(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
||||||
|
|||||||
18
cmd/git.go
18
cmd/git.go
@@ -12,7 +12,7 @@ type GitProjectInfo struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
ProjectName string
|
ProjectName string
|
||||||
BranchName string
|
BranchName string
|
||||||
GetLatestCommitOnRemote func(a *api) (string, error)
|
GetLatestCommitOnRemote func(a *Api) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -90,10 +90,10 @@ func GetCurrentBranchNameFromNativeGitCmd() (res string, e error) {
|
|||||||
|
|
||||||
/* Gets the project SSH or HTTPS url */
|
/* Gets the project SSH or HTTPS url */
|
||||||
func GetProjectUrlFromNativeGitCmd() (string, error) {
|
func GetProjectUrlFromNativeGitCmd() (string, error) {
|
||||||
cmd := exec.Command("git", "remote", "get-url", "origin")
|
cmd := exec.Command("git", "remote", "get-url", pluginOptions.ConnectionSettings.Remote)
|
||||||
url, err := cmd.Output()
|
url, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Could not get origin remote")
|
return "", fmt.Errorf("Could not get remote")
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.TrimSpace(string(url)), nil
|
return strings.TrimSpace(string(url)), nil
|
||||||
@@ -101,24 +101,24 @@ func GetProjectUrlFromNativeGitCmd() (string, error) {
|
|||||||
|
|
||||||
/* Pulls down latest commit information from Gitlab */
|
/* Pulls down latest commit information from Gitlab */
|
||||||
func RefreshProjectInfo() error {
|
func RefreshProjectInfo() error {
|
||||||
cmd := exec.Command("git", "fetch", "origin")
|
cmd := exec.Command("git", "fetch", pluginOptions.ConnectionSettings.Remote)
|
||||||
_, err := cmd.Output()
|
_, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to run `git fetch origin`: %v", err)
|
return fmt.Errorf("Failed to run `git fetch %s`: %v", pluginOptions.ConnectionSettings.Remote, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The GetLatestCommitOnRemote function is attached during the createRouterAndApi call, since it needs to be called every time to get the latest commit.
|
The GetLatestCommitOnRemote function is attached during the CreateRouterAndApi call, since it needs to be called every time to get the latest commit.
|
||||||
*/
|
*/
|
||||||
func GetLatestCommitOnRemote(a *api) (string, error) {
|
func GetLatestCommitOnRemote(a *Api) (string, error) {
|
||||||
cmd := exec.Command("git", "log", "-1", "--format=%H", fmt.Sprintf("origin/%s", a.gitInfo.BranchName))
|
cmd := exec.Command("git", "log", "-1", "--format=%H", fmt.Sprintf("%s/%s", pluginOptions.ConnectionSettings.Remote, a.gitInfo.BranchName))
|
||||||
|
|
||||||
out, err := cmd.Output()
|
out, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Failed to run `git log -1 --format=%%H " + fmt.Sprintf("origin/%s", a.gitInfo.BranchName))
|
return "", fmt.Errorf("Failed to run `git log -1 --format=%%H " + fmt.Sprintf("%s/%s", pluginOptions.ConnectionSettings.Remote, a.gitInfo.BranchName))
|
||||||
}
|
}
|
||||||
|
|
||||||
commit := strings.TrimSpace(string(out))
|
commit := strings.TrimSpace(string(out))
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ func TestExtractGitInfo_FailToGetCurrentBranchName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRefreshGitRemote_FailToRefreshRemote(t *testing.T) {
|
func TestRefreshGitRemote_FailToRefreshRemote(t *testing.T) {
|
||||||
expectedErrNestedMsg := "error when fetching origin commits"
|
expectedErrNestedMsg := "error when fetching commits"
|
||||||
_, actualErr := extractGitInfo(
|
_, actualErr := extractGitInfo(
|
||||||
func() error {
|
func() error {
|
||||||
return errors.New(expectedErrNestedMsg)
|
return errors.New(expectedErrNestedMsg)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type InfoResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* infoHandler fetches infomation about the current git project. The data returned here is used in many other API calls */
|
/* infoHandler fetches infomation about the current git project. The data returned here is used in many other API calls */
|
||||||
func (a *api) infoHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) infoHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
||||||
|
|||||||
@@ -1,52 +1,58 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getInfo(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestsOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return &gitlab.MergeRequest{Title: "Some Title"}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInfoNon200(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestsOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInfoErr(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestsOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInfoHandler(t *testing.T) {
|
func TestInfoHandler(t *testing.T) {
|
||||||
t.Run("Returns normal information", func(t *testing.T) {
|
t.Run("Returns normal information", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().GetMergeRequest("", mock_main.MergeId, &gitlab.GetMergeRequestsOptions{}).Return(&gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
request := makeRequest(t, http.MethodGet, "/mr/info", nil)
|
request := makeRequest(t, http.MethodGet, "/mr/info", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{getMergeRequest: getInfo})
|
|
||||||
data := serveRequest(t, server, request, InfoResponse{})
|
data := serveRequest(t, server, request, InfoResponse{})
|
||||||
assert(t, data.Info.Title, "Some Title")
|
|
||||||
assert(t, data.SuccessResponse.Message, "Merge requests retrieved")
|
assert(t, data.SuccessResponse.Message, "Merge requests retrieved")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-GET method", func(t *testing.T) {
|
t.Run("Disallows non-GET method", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/info", nil)
|
request := makeRequest(t, http.MethodPost, "/mr/info", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{getMergeRequest: getInfo})
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkBadMethod(t, *data, http.MethodGet)
|
checkBadMethod(t, *data, http.MethodGet)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().GetMergeRequest("", mock_main.MergeId, &gitlab.GetMergeRequestsOptions{}).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
request := makeRequest(t, http.MethodGet, "/mr/info", nil)
|
request := makeRequest(t, http.MethodGet, "/mr/info", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{getMergeRequest: getInfoErr})
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkErrorFromGitlab(t, *data, "Could not get project info")
|
checkErrorFromGitlab(t, *data, "Could not get project info")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().GetMergeRequest("", mock_main.MergeId, &gitlab.GetMergeRequestsOptions{}).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
request := makeRequest(t, http.MethodGet, "/mr/info", nil)
|
request := makeRequest(t, http.MethodGet, "/mr/info", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{getMergeRequest: getInfoNon200})
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkNon200(t, *data, "Could not get project info", "/mr/info")
|
checkNon200(t, *data, "Could not get project info", "/mr/info")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type JobTraceResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* jobHandler returns a string that shows the output of a specific job run in a Gitlab pipeline */
|
/* jobHandler returns a string that shows the output of a specific job run in a Gitlab pipeline */
|
||||||
func (a *api) jobHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) jobHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
||||||
|
|||||||
@@ -2,53 +2,58 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getTraceFile(pid interface{}, jobID int, options ...gitlab.RequestOptionFunc) (*bytes.Reader, *gitlab.Response, error) {
|
var jobId = 0
|
||||||
return bytes.NewReader([]byte("Some data")), makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTraceFileErr(pid interface{}, jobID int, options ...gitlab.RequestOptionFunc) (*bytes.Reader, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTraceFileNon200(pid interface{}, jobID int, options ...gitlab.RequestOptionFunc) (*bytes.Reader, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJobHandler(t *testing.T) {
|
func TestJobHandler(t *testing.T) {
|
||||||
t.Run("Should read a job trace file", func(t *testing.T) {
|
t.Run("Should read a job trace file", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().GetTraceFile("", jobId).Return(bytes.NewReader([]byte("Some data")), makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/job", JobTraceRequest{})
|
request := makeRequest(t, http.MethodGet, "/job", JobTraceRequest{})
|
||||||
server, _ := createRouterAndApi(fakeClient{getTraceFile: getTraceFile})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, JobTraceResponse{})
|
data := serveRequest(t, server, request, JobTraceResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Log file read")
|
assert(t, data.SuccessResponse.Message, "Log file read")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
assert(t, data.File, "Some data")
|
assert(t, data.File, "Some data")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-GET methods", func(t *testing.T) {
|
t.Run("Disallows non-GET methods", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().GetTraceFile("", jobId).Return(bytes.NewReader([]byte("Some data")), makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/job", JobTraceRequest{})
|
request := makeRequest(t, http.MethodPost, "/job", JobTraceRequest{})
|
||||||
server, _ := createRouterAndApi(fakeClient{getTraceFile: getTraceFile})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkBadMethod(t, *data, http.MethodGet)
|
checkBadMethod(t, *data, http.MethodGet)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should handle errors from Gitlab", func(t *testing.T) {
|
t.Run("Should handle errors from Gitlab", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().GetTraceFile("", jobId).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/job", JobTraceRequest{})
|
request := makeRequest(t, http.MethodGet, "/job", JobTraceRequest{})
|
||||||
server, _ := createRouterAndApi(fakeClient{getTraceFile: getTraceFileErr})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not get trace file for job")
|
checkErrorFromGitlab(t, *data, "Could not get trace file for job")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should handle non-200s", func(t *testing.T) {
|
t.Run("Should handle non-2jobIdjobIds", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().GetTraceFile("", jobId).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/job", JobTraceRequest{})
|
request := makeRequest(t, http.MethodGet, "/job", JobTraceRequest{})
|
||||||
server, _ := createRouterAndApi(fakeClient{getTraceFile: getTraceFileNon200})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkNon200(t, *data, "Could not get trace file for job", "/job")
|
checkNon200(t, *data, "Could not get trace file for job", "/job")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ type LabelsRequestResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* labelsHandler adds or removes labels from a merge request, and returns all labels for the current project */
|
/* labelsHandler adds or removes labels from a merge request, and returns all labels for the current project */
|
||||||
func (a *api) labelHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) labelHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
a.getLabels(w, r)
|
a.getLabels(w, r)
|
||||||
@@ -42,7 +42,7 @@ func (a *api) labelHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *api) getLabels(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) getLabels(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
labels, res, err := a.client.ListLabels(a.projectInfo.ProjectId, &gitlab.ListLabelsOptions{})
|
labels, res, err := a.client.ListLabels(a.projectInfo.ProjectId, &gitlab.ListLabelsOptions{})
|
||||||
@@ -82,7 +82,7 @@ func (a *api) getLabels(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *api) updateLabels(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) updateLabels(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func (n SortableDiscussions) Swap(i, j int) {
|
|||||||
listDiscussionsHandler lists all discusions for a given merge request, both those linked and unlinked to particular points in the code.
|
listDiscussionsHandler lists all discusions for a given merge request, both those linked and unlinked to particular points in the code.
|
||||||
The responses are sorted by date created, and blacklisted users are not included
|
The responses are sorted by date created, and blacklisted users are not included
|
||||||
*/
|
*/
|
||||||
func (a *api) listDiscussionsHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) listDiscussionsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
||||||
@@ -68,7 +68,7 @@ func (a *api) listDiscussionsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
PerPage: 250,
|
PerPage: 250,
|
||||||
}
|
}
|
||||||
|
|
||||||
discussions, res, err := a.client.ListMergeRequestDiscussions(a.projectInfo.ProjectId, a.projectInfo.MergeId, &mergeRequestDiscussionOptions, nil)
|
discussions, res, err := a.client.ListMergeRequestDiscussions(a.projectInfo.ProjectId, a.projectInfo.MergeId, &mergeRequestDiscussionOptions)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(w, err, "Could not list discussions", http.StatusInternalServerError)
|
handleError(w, err, "Could not list discussions", http.StatusInternalServerError)
|
||||||
|
|||||||
@@ -1,18 +1,29 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func listMergeRequestDiscussions(pid interface{}, mergeRequest int, opt *gitlab.ListMergeRequestDiscussionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Discussion, *gitlab.Response, error) {
|
var now = time.Now()
|
||||||
now := time.Now()
|
var newer = now.Add(time.Second * 100)
|
||||||
newer := now.Add(time.Second * 100)
|
|
||||||
discussions := []*gitlab.Discussion{
|
type Author struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
State string `json:"state"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
WebURL string `json:"web_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var testListDiscussionsResponse = []*gitlab.Discussion{
|
||||||
{
|
{
|
||||||
Notes: []*gitlab.Note{
|
Notes: []*gitlab.Note{
|
||||||
{
|
{
|
||||||
@@ -36,30 +47,18 @@ func listMergeRequestDiscussions(pid interface{}, mergeRequest int, opt *gitlab.
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return discussions, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listMergeRequestDiscussionsErr(pid interface{}, mergeRequest int, opt *gitlab.ListMergeRequestDiscussionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Discussion, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func listMergeRequestDiscussionsNon200(pid interface{}, mergeRequest int, opt *gitlab.ListMergeRequestDiscussionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Discussion, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listMergeRequestAwardEmojiOnNote(pid interface{}, mr int, noteID int, opt *gitlab.ListAwardEmojiOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.AwardEmoji, *gitlab.Response, error) {
|
|
||||||
return []*gitlab.AwardEmoji{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listMergeRequestAwardEmojiOnNoteFailure(pid interface{}, mr int, noteID int, opt *gitlab.ListAwardEmojiOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.AwardEmoji, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusBadRequest), errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListDiscussionsHandler(t *testing.T) {
|
func TestListDiscussionsHandler(t *testing.T) {
|
||||||
t.Run("Returns sorted discussions", func(t *testing.T) {
|
t.Run("Returns sorted discussions", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListMergeRequestDiscussions("", mock_main.MergeId, gomock.Any()).Return(testListDiscussionsResponse, makeResponse(http.StatusOK), nil)
|
||||||
|
client.EXPECT().ListMergeRequestAwardEmojiOnNote("", mock_main.MergeId, gomock.Any(), gomock.Any()).Return([]*gitlab.AwardEmoji{}, makeResponse(http.StatusOK), nil).Times(2)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{})
|
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{})
|
||||||
server, _ := createRouterAndApi(fakeClient{listMergeRequestDiscussions: listMergeRequestDiscussions, listMergeRequestAwardEmojiOnNote: listMergeRequestAwardEmojiOnNote})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, DiscussionsResponse{})
|
data := serveRequest(t, server, request, DiscussionsResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Discussions retrieved")
|
assert(t, data.SuccessResponse.Message, "Discussions retrieved")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
assert(t, data.Discussions[0].Notes[0].Author.Username, "hcramer2") /* Sorting applied */
|
assert(t, data.Discussions[0].Notes[0].Author.Username, "hcramer2") /* Sorting applied */
|
||||||
@@ -67,9 +66,15 @@ func TestListDiscussionsHandler(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Uses blacklist to filter unwanted authors", func(t *testing.T) {
|
t.Run("Uses blacklist to filter unwanted authors", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListMergeRequestDiscussions("", mock_main.MergeId, gomock.Any()).Return(testListDiscussionsResponse, makeResponse(http.StatusOK), nil)
|
||||||
|
client.EXPECT().ListMergeRequestAwardEmojiOnNote("", mock_main.MergeId, gomock.Any(), gomock.Any()).Return([]*gitlab.AwardEmoji{}, makeResponse(http.StatusOK), nil).Times(2)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{Blacklist: []string{"hcramer"}})
|
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{Blacklist: []string{"hcramer"}})
|
||||||
server, _ := createRouterAndApi(fakeClient{listMergeRequestDiscussions: listMergeRequestDiscussions, listMergeRequestAwardEmojiOnNote: listMergeRequestAwardEmojiOnNote})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, DiscussionsResponse{})
|
data := serveRequest(t, server, request, DiscussionsResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Discussions retrieved")
|
assert(t, data.SuccessResponse.Message, "Discussions retrieved")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
assert(t, len(data.Discussions), 1)
|
assert(t, len(data.Discussions), 1)
|
||||||
@@ -77,30 +82,51 @@ func TestListDiscussionsHandler(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-POST method", func(t *testing.T) {
|
t.Run("Disallows non-POST method", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPatch, "/mr/discussions/list", DiscussionsRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{listMergeRequestDiscussions: listMergeRequestDiscussions, listMergeRequestAwardEmojiOnNote: listMergeRequestAwardEmojiOnNote})
|
mock_main.WithMr(t, client)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPut, "/mr/discussions/list", DiscussionsRequest{})
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkBadMethod(t, *data, http.MethodPost)
|
checkBadMethod(t, *data, http.MethodPost)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListMergeRequestDiscussions("", mock_main.MergeId, gomock.Any()).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{})
|
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{})
|
||||||
server, _ := createRouterAndApi(fakeClient{listMergeRequestDiscussions: listMergeRequestDiscussionsErr, listMergeRequestAwardEmojiOnNote: listMergeRequestAwardEmojiOnNote})
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkErrorFromGitlab(t, *data, "Could not list discussions")
|
checkErrorFromGitlab(t, *data, "Could not list discussions")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListMergeRequestDiscussions("", mock_main.MergeId, gomock.Any()).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{})
|
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{})
|
||||||
server, _ := createRouterAndApi(fakeClient{listMergeRequestDiscussions: listMergeRequestDiscussionsNon200, listMergeRequestAwardEmojiOnNote: listMergeRequestAwardEmojiOnNote})
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkNon200(t, *data, "Could not list discussions", "/mr/discussions/list")
|
checkNon200(t, *data, "Could not list discussions", "/mr/discussions/list")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles error from emoji service", func(t *testing.T) {
|
t.Run("Handles error from emoji service", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListMergeRequestDiscussions("", mock_main.MergeId, gomock.Any()).Return(testListDiscussionsResponse, makeResponse(http.StatusOK), nil)
|
||||||
|
client.EXPECT().ListMergeRequestAwardEmojiOnNote("", mock_main.MergeId, gomock.Any(), gomock.Any()).Return(nil, nil, errorFromGitlab).Times(2)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{})
|
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{})
|
||||||
server, _ := createRouterAndApi(fakeClient{listMergeRequestDiscussions: listMergeRequestDiscussions, listMergeRequestAwardEmojiOnNote: listMergeRequestAwardEmojiOnNoteFailure})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not fetch emojis")
|
checkErrorFromGitlab(t, *data, "Could not fetch emojis")
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
25
cmd/main.go
25
cmd/main.go
@@ -1,11 +1,36 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PluginOptions struct {
|
||||||
|
GitlabUrl string `json:"gitlab_url"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
AuthToken string `json:"auth_token"`
|
||||||
|
LogPath string `json:"log_path"`
|
||||||
|
Debug struct {
|
||||||
|
Request bool `json:"go_request"`
|
||||||
|
Response bool `json:"go_response"`
|
||||||
|
} `json:"debug"`
|
||||||
|
ConnectionSettings struct {
|
||||||
|
Insecure bool `json:"insecure"`
|
||||||
|
Remote string `json:"remote"`
|
||||||
|
} `json:"connection_settings"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var pluginOptions PluginOptions
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(os.Args[1]), &pluginOptions)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failure parsing plugin settings: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
gitInfo, err := extractGitInfo(RefreshProjectInfo, GetProjectUrlFromNativeGitCmd, GetCurrentBranchNameFromNativeGitCmd)
|
gitInfo, err := extractGitInfo(RefreshProjectInfo, GetProjectUrlFromNativeGitCmd, GetCurrentBranchNameFromNativeGitCmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failure initializing plugin: %v", err)
|
log.Fatalf("Failure initializing plugin: %v", err)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type ProjectMembersResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* projectMembersHandler returns all members of the current Gitlab project */
|
/* projectMembersHandler returns all members of the current Gitlab project */
|
||||||
func (a *api) projectMembersHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) projectMembersHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
||||||
|
|||||||
@@ -1,52 +1,56 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func listAllProjectMembers(pid interface{}, opt *gitlab.ListProjectMembersOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectMember, *gitlab.Response, error) {
|
|
||||||
return []*gitlab.ProjectMember{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listAllProjectMembersErr(pid interface{}, opt *gitlab.ListProjectMembersOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectMember, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func listAllProjectMembersNon200(pid interface{}, opt *gitlab.ListProjectMembersOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectMember, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMembersHandler(t *testing.T) {
|
func TestMembersHandler(t *testing.T) {
|
||||||
t.Run("Returns project members", func(t *testing.T) {
|
t.Run("Returns project members", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().ListAllProjectMembers("", gomock.Any()).Return([]*gitlab.ProjectMember{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/project/members", nil)
|
request := makeRequest(t, http.MethodGet, "/project/members", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{listAllProjectMembers: listAllProjectMembers})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ProjectMembersResponse{})
|
data := serveRequest(t, server, request, ProjectMembersResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Project members retrieved")
|
assert(t, data.SuccessResponse.Message, "Project members retrieved")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-GET method", func(t *testing.T) {
|
t.Run("Disallows non-GET method", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/project/members", nil)
|
request := makeRequest(t, http.MethodPost, "/project/members", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{listAllProjectMembers: listAllProjectMembers})
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkBadMethod(t, *data, http.MethodGet)
|
checkBadMethod(t, *data, http.MethodGet)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().ListAllProjectMembers("", gomock.Any()).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/project/members", nil)
|
request := makeRequest(t, http.MethodGet, "/project/members", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{listAllProjectMembers: listAllProjectMembersErr})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not retrieve project members")
|
checkErrorFromGitlab(t, *data, "Could not retrieve project members")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().ListAllProjectMembers("", gomock.Any()).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/project/members", nil)
|
request := makeRequest(t, http.MethodGet, "/project/members", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{listAllProjectMembers: listAllProjectMembersNon200})
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkNon200(t, *data, "Could not retrieve project members", "/project/members")
|
checkNon200(t, *data, "Could not retrieve project members", "/project/members")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type AcceptMergeRequestRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* acceptAndMergeHandler merges a given merge request into the target branch */
|
/* acceptAndMergeHandler merges a given merge request into the target branch */
|
||||||
func (a *api) acceptAndMergeHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) acceptAndMergeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
|
|||||||
@@ -4,35 +4,63 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ListMergeRequestRequest struct {
|
||||||
|
Label []string `json:"label"`
|
||||||
|
NotLabel []string `json:"notlabel"`
|
||||||
|
}
|
||||||
|
|
||||||
type ListMergeRequestResponse struct {
|
type ListMergeRequestResponse struct {
|
||||||
SuccessResponse
|
SuccessResponse
|
||||||
MergeRequests []*gitlab.MergeRequest `json:"merge_requests"`
|
MergeRequests []*gitlab.MergeRequest `json:"merge_requests"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *api) mergeRequestsHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) mergeRequestsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
||||||
|
handleError(w, InvalidRequestError{}, "Expected POST", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if r.Method != http.MethodGet {
|
body, err := io.ReadAll(r.Body)
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
if err != nil {
|
||||||
handleError(w, InvalidRequestError{}, "Expected GET", http.StatusMethodNotAllowed)
|
handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer r.Body.Close()
|
||||||
|
var listMergeRequestRequest ListMergeRequestRequest
|
||||||
|
err = json.Unmarshal(body, &listMergeRequestRequest)
|
||||||
|
if err != nil {
|
||||||
|
handleError(w, err, "Could not read JSON from request", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
options := gitlab.ListProjectMergeRequestsOptions{
|
options := gitlab.ListProjectMergeRequestsOptions{
|
||||||
Scope: gitlab.Ptr("all"),
|
Scope: gitlab.Ptr("all"),
|
||||||
State: gitlab.Ptr("opened"),
|
State: gitlab.Ptr("opened"),
|
||||||
|
Labels: (*gitlab.LabelOptions)(&listMergeRequestRequest.Label),
|
||||||
|
NotLabels: (*gitlab.LabelOptions)(&listMergeRequestRequest.NotLabel),
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeRequests, _, err := a.client.ListProjectMergeRequests(a.projectInfo.ProjectId, &options)
|
mergeRequests, res, err := a.client.ListProjectMergeRequests(a.projectInfo.ProjectId, &options)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(w, fmt.Errorf("Failed to list merge requests: %w", err), "Failed to list merge requests", http.StatusInternalServerError)
|
handleError(w, fmt.Errorf("Failed to list merge requests: %w", err), "Failed to list merge requests", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if res.StatusCode >= 300 {
|
||||||
|
handleError(w, GenericError{endpoint: "/merge_requests"}, "Failed to list merge requests", res.StatusCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if len(mergeRequests) == 0 {
|
if len(mergeRequests) == 0 {
|
||||||
handleError(w, errors.New("No merge requests found"), "No merge requests found", http.StatusNotFound)
|
handleError(w, errors.New("No merge requests found"), "No merge requests found", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
@@ -51,5 +79,4 @@ func (a *api) mergeRequestsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(w, err, "Could not encode response", http.StatusInternalServerError)
|
handleError(w, err, "Could not encode response", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,72 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func listProjectMergeRequests200(pid interface{}, opt *gitlab.ListProjectMergeRequestsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequest, *gitlab.Response, error) {
|
var testListMergeRequestsRequest = ListMergeRequestRequest{
|
||||||
return []*gitlab.MergeRequest{{ID: 1}}, &gitlab.Response{}, nil
|
Label: []string{},
|
||||||
}
|
NotLabel: []string{},
|
||||||
|
|
||||||
func listProjectMergeRequestsEmpty(pid interface{}, opt *gitlab.ListProjectMergeRequestsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return []*gitlab.MergeRequest{}, &gitlab.Response{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listProjectMergeRequestsErr(pid interface{}, opt *gitlab.ListProjectMergeRequestsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMergeRequestHandler(t *testing.T) {
|
func TestMergeRequestHandler(t *testing.T) {
|
||||||
t.Run("Should fetch merge requests", func(t *testing.T) {
|
t.Run("Should fetch merge requests", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodGet, "/merge_requests", nil)
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{listProjectMergeRequests: listProjectMergeRequests200})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListProjectMergeRequests("", gomock.Any()).Return([]*gitlab.MergeRequest{
|
||||||
|
{
|
||||||
|
IID: 10,
|
||||||
|
},
|
||||||
|
}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/merge_requests", testListMergeRequestsRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ListMergeRequestResponse{})
|
data := serveRequest(t, server, request, ListMergeRequestResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Merge requests fetched successfully")
|
assert(t, data.Message, "Merge requests fetched successfully")
|
||||||
assert(t, data.Status, http.StatusOK)
|
assert(t, data.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
t.Run("Should handle an error", func(t *testing.T) {
|
|
||||||
request := makeRequest(t, http.MethodGet, "/merge_requests", nil)
|
t.Run("Should handle an error from Gitlab", func(t *testing.T) {
|
||||||
server, _ := createRouterAndApi(fakeClient{listProjectMergeRequests: listProjectMergeRequestsErr})
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListProjectMergeRequests("", gomock.Any()).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/merge_requests", testListMergeRequestsRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "Failed to list merge requests")
|
assert(t, data.Message, "Failed to list merge requests")
|
||||||
assert(t, data.Status, http.StatusInternalServerError)
|
assert(t, data.Status, http.StatusInternalServerError)
|
||||||
})
|
})
|
||||||
t.Run("Should handle not having any merge requests with 404", func(t *testing.T) {
|
|
||||||
request := makeRequest(t, http.MethodGet, "/merge_requests", nil)
|
t.Run("Should handle a non-200", func(t *testing.T) {
|
||||||
server, _ := createRouterAndApi(fakeClient{listProjectMergeRequests: listProjectMergeRequestsEmpty})
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListProjectMergeRequests("", gomock.Any()).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/merge_requests", testListMergeRequestsRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
|
assert(t, data.Message, "Failed to list merge requests")
|
||||||
|
assert(t, data.Status, http.StatusSeeOther)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should handle not having any merge requests with 404", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().ListProjectMergeRequests("", gomock.Any()).Return([]*gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/merge_requests", testListMergeRequestsRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
data := serveRequest(t, server, request, ListMergeRequestResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "No merge requests found")
|
assert(t, data.Message, "No merge requests found")
|
||||||
assert(t, data.Status, http.StatusNotFound)
|
assert(t, data.Status, http.StatusNotFound)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,52 +1,67 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func acceptMergeRequest(pid interface{}, mergeRequest int, opt *gitlab.AcceptMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
var testAcceptMergeRequestPayload = AcceptMergeRequestRequest{
|
||||||
return &gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil
|
Squash: false,
|
||||||
}
|
SquashMessage: "Squash me!",
|
||||||
|
DeleteBranch: false,
|
||||||
func acceptMergeRequestErr(pid interface{}, mergeRequest int, opt *gitlab.AcceptMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func acceptAndMergeNon200(pid interface{}, mergeRequest int, opt *gitlab.AcceptMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAcceptAndMergeHandler(t *testing.T) {
|
func TestAcceptAndMergeHandler(t *testing.T) {
|
||||||
t.Run("Accepts and merges a merge request", func(t *testing.T) {
|
t.Run("Accepts and merges a merge request", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/merge", AcceptMergeRequestRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{acceptMergeRequest: acceptMergeRequest})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().AcceptMergeRequest("", mock_main.MergeId, gomock.Any()).Return(&gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/merge", testAcceptMergeRequestPayload)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, SuccessResponse{})
|
data := serveRequest(t, server, request, SuccessResponse{})
|
||||||
|
|
||||||
assert(t, data.Message, "MR merged successfully")
|
assert(t, data.Message, "MR merged successfully")
|
||||||
assert(t, data.Status, http.StatusOK)
|
assert(t, data.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-POST methods", func(t *testing.T) {
|
t.Run("Disallows non-POST methods", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodGet, "/mr/merge", AcceptMergeRequestRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{acceptMergeRequest: acceptMergeRequest})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().AcceptMergeRequest("", mock_main.MergeId, gomock.Any()).Return(&gitlab.MergeRequest{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPatch, "/mr/merge", testAcceptMergeRequestPayload)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkBadMethod(t, *data, http.MethodPost)
|
checkBadMethod(t, *data, http.MethodPost)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/merge", AcceptMergeRequestRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{acceptMergeRequest: acceptMergeRequestErr})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().AcceptMergeRequest("", mock_main.MergeId, gomock.Any()).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/merge", testAcceptMergeRequestPayload)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not merge MR")
|
checkErrorFromGitlab(t, *data, "Could not merge MR")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/merge", AcceptMergeRequestRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{acceptMergeRequest: acceptAndMergeNon200})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().AcceptMergeRequest("", mock_main.MergeId, gomock.Any()).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/merge", testAcceptMergeRequestPayload)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
|
||||||
checkNon200(t, *data, "Could not merge MR", "/mr/merge")
|
checkNon200(t, *data, "Could not merge MR", "/mr/merge")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
686
cmd/mocks/fake_client.go
Normal file
686
cmd/mocks/fake_client.go
Normal file
@@ -0,0 +1,686 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: cmd/types.go
|
||||||
|
//
|
||||||
|
// Generated by this command:
|
||||||
|
//
|
||||||
|
// mockgen -source cmd/types.go
|
||||||
|
//
|
||||||
|
|
||||||
|
// Package mock_main is a generated GoMock package.
|
||||||
|
package mock_main
|
||||||
|
|
||||||
|
import (
|
||||||
|
bytes "bytes"
|
||||||
|
io "io"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
gitlab "github.com/xanzy/go-gitlab"
|
||||||
|
gomock "go.uber.org/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockClientInterface is a mock of ClientInterface interface.
|
||||||
|
type MockClientInterface struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockClientInterfaceMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockClientInterfaceMockRecorder is the mock recorder for MockClientInterface.
|
||||||
|
type MockClientInterfaceMockRecorder struct {
|
||||||
|
mock *MockClientInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockClientInterface creates a new mock instance.
|
||||||
|
func NewMockClientInterface(ctrl *gomock.Controller) *MockClientInterface {
|
||||||
|
mock := &MockClientInterface{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockClientInterfaceMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockClientInterface) EXPECT() *MockClientInterfaceMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcceptMergeRequest mocks base method.
|
||||||
|
func (m *MockClientInterface) AcceptMergeRequest(pid any, mergeRequestIID int, opt *gitlab.AcceptMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "AcceptMergeRequest", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.MergeRequest)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcceptMergeRequest indicates an expected call of AcceptMergeRequest.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) AcceptMergeRequest(pid, mergeRequestIID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AcceptMergeRequest", reflect.TypeOf((*MockClientInterface)(nil).AcceptMergeRequest), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMergeRequestDiscussionNote mocks base method.
|
||||||
|
func (m *MockClientInterface) AddMergeRequestDiscussionNote(pid any, mergeRequestIID int, discussion string, opt *gitlab.AddMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, discussion, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "AddMergeRequestDiscussionNote", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Note)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMergeRequestDiscussionNote indicates an expected call of AddMergeRequestDiscussionNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) AddMergeRequestDiscussionNote(pid, mergeRequestIID, discussion, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, discussion, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddMergeRequestDiscussionNote", reflect.TypeOf((*MockClientInterface)(nil).AddMergeRequestDiscussionNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApproveMergeRequest mocks base method.
|
||||||
|
func (m *MockClientInterface) ApproveMergeRequest(pid any, mergeRequestIID int, opt *gitlab.ApproveMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequestApprovals, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ApproveMergeRequest", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.MergeRequestApprovals)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApproveMergeRequest indicates an expected call of ApproveMergeRequest.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ApproveMergeRequest(pid, mergeRequestIID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApproveMergeRequest", reflect.TypeOf((*MockClientInterface)(nil).ApproveMergeRequest), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateDraftNote mocks base method.
|
||||||
|
func (m *MockClientInterface) CreateDraftNote(pid any, mergeRequestIID int, opt *gitlab.CreateDraftNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.DraftNote, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "CreateDraftNote", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.DraftNote)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateDraftNote indicates an expected call of CreateDraftNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) CreateDraftNote(pid, mergeRequestIID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateDraftNote", reflect.TypeOf((*MockClientInterface)(nil).CreateDraftNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMergeRequest mocks base method.
|
||||||
|
func (m *MockClientInterface) CreateMergeRequest(pid any, opt *gitlab.CreateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "CreateMergeRequest", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.MergeRequest)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMergeRequest indicates an expected call of CreateMergeRequest.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) CreateMergeRequest(pid, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMergeRequest", reflect.TypeOf((*MockClientInterface)(nil).CreateMergeRequest), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMergeRequestAwardEmojiOnNote mocks base method.
|
||||||
|
func (m *MockClientInterface) CreateMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int, opt *gitlab.CreateAwardEmojiOptions, options ...gitlab.RequestOptionFunc) (*gitlab.AwardEmoji, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, noteID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "CreateMergeRequestAwardEmojiOnNote", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.AwardEmoji)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMergeRequestAwardEmojiOnNote indicates an expected call of CreateMergeRequestAwardEmojiOnNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) CreateMergeRequestAwardEmojiOnNote(pid, mergeRequestIID, noteID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, noteID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMergeRequestAwardEmojiOnNote", reflect.TypeOf((*MockClientInterface)(nil).CreateMergeRequestAwardEmojiOnNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMergeRequestDiscussion mocks base method.
|
||||||
|
func (m *MockClientInterface) CreateMergeRequestDiscussion(pid any, mergeRequestIID int, opt *gitlab.CreateMergeRequestDiscussionOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Discussion, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "CreateMergeRequestDiscussion", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Discussion)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMergeRequestDiscussion indicates an expected call of CreateMergeRequestDiscussion.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) CreateMergeRequestDiscussion(pid, mergeRequestIID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMergeRequestDiscussion", reflect.TypeOf((*MockClientInterface)(nil).CreateMergeRequestDiscussion), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrentUser mocks base method.
|
||||||
|
func (m *MockClientInterface) CurrentUser(options ...gitlab.RequestOptionFunc) (*gitlab.User, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "CurrentUser", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.User)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrentUser indicates an expected call of CurrentUser.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) CurrentUser(options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentUser", reflect.TypeOf((*MockClientInterface)(nil).CurrentUser), options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDraftNote mocks base method.
|
||||||
|
func (m *MockClientInterface) DeleteDraftNote(pid any, mergeRequest, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequest, note}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "DeleteDraftNote", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Response)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDraftNote indicates an expected call of DeleteDraftNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) DeleteDraftNote(pid, mergeRequest, note any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequest, note}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDraftNote", reflect.TypeOf((*MockClientInterface)(nil).DeleteDraftNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMergeRequestAwardEmojiOnNote mocks base method.
|
||||||
|
func (m *MockClientInterface) DeleteMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID, awardID int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, noteID, awardID}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "DeleteMergeRequestAwardEmojiOnNote", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Response)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMergeRequestAwardEmojiOnNote indicates an expected call of DeleteMergeRequestAwardEmojiOnNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) DeleteMergeRequestAwardEmojiOnNote(pid, mergeRequestIID, noteID, awardID any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, noteID, awardID}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteMergeRequestAwardEmojiOnNote", reflect.TypeOf((*MockClientInterface)(nil).DeleteMergeRequestAwardEmojiOnNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMergeRequestDiscussionNote mocks base method.
|
||||||
|
func (m *MockClientInterface) DeleteMergeRequestDiscussionNote(pid any, mergeRequestIID int, discussion string, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, discussion, note}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "DeleteMergeRequestDiscussionNote", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Response)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMergeRequestDiscussionNote indicates an expected call of DeleteMergeRequestDiscussionNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) DeleteMergeRequestDiscussionNote(pid, mergeRequestIID, discussion, note any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, discussion, note}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteMergeRequestDiscussionNote", reflect.TypeOf((*MockClientInterface)(nil).DeleteMergeRequestDiscussionNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMergeRequest mocks base method.
|
||||||
|
func (m *MockClientInterface) GetMergeRequest(pid any, mergeRequestIID int, opt *gitlab.GetMergeRequestsOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "GetMergeRequest", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.MergeRequest)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMergeRequest indicates an expected call of GetMergeRequest.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) GetMergeRequest(pid, mergeRequestIID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMergeRequest", reflect.TypeOf((*MockClientInterface)(nil).GetMergeRequest), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMergeRequestDiffVersions mocks base method.
|
||||||
|
func (m *MockClientInterface) GetMergeRequestDiffVersions(pid any, mergeRequestIID int, opt *gitlab.GetMergeRequestDiffVersionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiffVersion, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "GetMergeRequestDiffVersions", varargs...)
|
||||||
|
ret0, _ := ret[0].([]*gitlab.MergeRequestDiffVersion)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMergeRequestDiffVersions indicates an expected call of GetMergeRequestDiffVersions.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) GetMergeRequestDiffVersions(pid, mergeRequestIID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMergeRequestDiffVersions", reflect.TypeOf((*MockClientInterface)(nil).GetMergeRequestDiffVersions), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTraceFile mocks base method.
|
||||||
|
func (m *MockClientInterface) GetTraceFile(pid any, jobID int, options ...gitlab.RequestOptionFunc) (*bytes.Reader, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, jobID}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "GetTraceFile", varargs...)
|
||||||
|
ret0, _ := ret[0].(*bytes.Reader)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTraceFile indicates an expected call of GetTraceFile.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) GetTraceFile(pid, jobID any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, jobID}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTraceFile", reflect.TypeOf((*MockClientInterface)(nil).GetTraceFile), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAllProjectMembers mocks base method.
|
||||||
|
func (m *MockClientInterface) ListAllProjectMembers(pid any, opt *gitlab.ListProjectMembersOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectMember, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ListAllProjectMembers", varargs...)
|
||||||
|
ret0, _ := ret[0].([]*gitlab.ProjectMember)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAllProjectMembers indicates an expected call of ListAllProjectMembers.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ListAllProjectMembers(pid, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAllProjectMembers", reflect.TypeOf((*MockClientInterface)(nil).ListAllProjectMembers), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListDraftNotes mocks base method.
|
||||||
|
func (m *MockClientInterface) ListDraftNotes(pid any, mergeRequest int, opt *gitlab.ListDraftNotesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.DraftNote, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequest, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ListDraftNotes", varargs...)
|
||||||
|
ret0, _ := ret[0].([]*gitlab.DraftNote)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListDraftNotes indicates an expected call of ListDraftNotes.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ListDraftNotes(pid, mergeRequest, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequest, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListDraftNotes", reflect.TypeOf((*MockClientInterface)(nil).ListDraftNotes), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListLabels mocks base method.
|
||||||
|
func (m *MockClientInterface) ListLabels(pid any, opt *gitlab.ListLabelsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Label, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ListLabels", varargs...)
|
||||||
|
ret0, _ := ret[0].([]*gitlab.Label)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListLabels indicates an expected call of ListLabels.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ListLabels(pid, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListLabels", reflect.TypeOf((*MockClientInterface)(nil).ListLabels), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMergeRequestAwardEmojiOnNote mocks base method.
|
||||||
|
func (m *MockClientInterface) ListMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int, opt *gitlab.ListAwardEmojiOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.AwardEmoji, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, noteID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ListMergeRequestAwardEmojiOnNote", varargs...)
|
||||||
|
ret0, _ := ret[0].([]*gitlab.AwardEmoji)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMergeRequestAwardEmojiOnNote indicates an expected call of ListMergeRequestAwardEmojiOnNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ListMergeRequestAwardEmojiOnNote(pid, mergeRequestIID, noteID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, noteID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListMergeRequestAwardEmojiOnNote", reflect.TypeOf((*MockClientInterface)(nil).ListMergeRequestAwardEmojiOnNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMergeRequestDiscussions mocks base method.
|
||||||
|
func (m *MockClientInterface) ListMergeRequestDiscussions(pid any, mergeRequestIID int, opt *gitlab.ListMergeRequestDiscussionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Discussion, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ListMergeRequestDiscussions", varargs...)
|
||||||
|
ret0, _ := ret[0].([]*gitlab.Discussion)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMergeRequestDiscussions indicates an expected call of ListMergeRequestDiscussions.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ListMergeRequestDiscussions(pid, mergeRequestIID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListMergeRequestDiscussions", reflect.TypeOf((*MockClientInterface)(nil).ListMergeRequestDiscussions), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPipelineJobs mocks base method.
|
||||||
|
func (m *MockClientInterface) ListPipelineJobs(pid any, pipelineID int, opts *gitlab.ListJobsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Job, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, pipelineID, opts}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ListPipelineJobs", varargs...)
|
||||||
|
ret0, _ := ret[0].([]*gitlab.Job)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPipelineJobs indicates an expected call of ListPipelineJobs.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ListPipelineJobs(pid, pipelineID, opts any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, pipelineID, opts}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListPipelineJobs", reflect.TypeOf((*MockClientInterface)(nil).ListPipelineJobs), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListProjectMergeRequests mocks base method.
|
||||||
|
func (m *MockClientInterface) ListProjectMergeRequests(pid any, opt *gitlab.ListProjectMergeRequestsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequest, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ListProjectMergeRequests", varargs...)
|
||||||
|
ret0, _ := ret[0].([]*gitlab.MergeRequest)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListProjectMergeRequests indicates an expected call of ListProjectMergeRequests.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ListProjectMergeRequests(pid, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListProjectMergeRequests", reflect.TypeOf((*MockClientInterface)(nil).ListProjectMergeRequests), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListProjectPipelines mocks base method.
|
||||||
|
func (m *MockClientInterface) ListProjectPipelines(pid any, opt *gitlab.ListProjectPipelinesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.PipelineInfo, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ListProjectPipelines", varargs...)
|
||||||
|
ret0, _ := ret[0].([]*gitlab.PipelineInfo)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListProjectPipelines indicates an expected call of ListProjectPipelines.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ListProjectPipelines(pid, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListProjectPipelines", reflect.TypeOf((*MockClientInterface)(nil).ListProjectPipelines), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublishAllDraftNotes mocks base method.
|
||||||
|
func (m *MockClientInterface) PublishAllDraftNotes(pid any, mergeRequest int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequest}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "PublishAllDraftNotes", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Response)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublishAllDraftNotes indicates an expected call of PublishAllDraftNotes.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) PublishAllDraftNotes(pid, mergeRequest any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequest}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishAllDraftNotes", reflect.TypeOf((*MockClientInterface)(nil).PublishAllDraftNotes), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublishDraftNote mocks base method.
|
||||||
|
func (m *MockClientInterface) PublishDraftNote(pid any, mergeRequest, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequest, note}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "PublishDraftNote", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Response)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublishDraftNote indicates an expected call of PublishDraftNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) PublishDraftNote(pid, mergeRequest, note any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequest, note}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishDraftNote", reflect.TypeOf((*MockClientInterface)(nil).PublishDraftNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveMergeRequestDiscussion mocks base method.
|
||||||
|
func (m *MockClientInterface) ResolveMergeRequestDiscussion(pid any, mergeRequestIID int, discussion string, opt *gitlab.ResolveMergeRequestDiscussionOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Discussion, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, discussion, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ResolveMergeRequestDiscussion", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Discussion)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveMergeRequestDiscussion indicates an expected call of ResolveMergeRequestDiscussion.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) ResolveMergeRequestDiscussion(pid, mergeRequestIID, discussion, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, discussion, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveMergeRequestDiscussion", reflect.TypeOf((*MockClientInterface)(nil).ResolveMergeRequestDiscussion), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetryPipelineBuild mocks base method.
|
||||||
|
func (m *MockClientInterface) RetryPipelineBuild(pid any, pipeline int, options ...gitlab.RequestOptionFunc) (*gitlab.Pipeline, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, pipeline}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "RetryPipelineBuild", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Pipeline)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetryPipelineBuild indicates an expected call of RetryPipelineBuild.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) RetryPipelineBuild(pid, pipeline any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, pipeline}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetryPipelineBuild", reflect.TypeOf((*MockClientInterface)(nil).RetryPipelineBuild), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnapproveMergeRequest mocks base method.
|
||||||
|
func (m *MockClientInterface) UnapproveMergeRequest(pid any, mergeRequestIID int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "UnapproveMergeRequest", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Response)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnapproveMergeRequest indicates an expected call of UnapproveMergeRequest.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) UnapproveMergeRequest(pid, mergeRequestIID any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnapproveMergeRequest", reflect.TypeOf((*MockClientInterface)(nil).UnapproveMergeRequest), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDraftNote mocks base method.
|
||||||
|
func (m *MockClientInterface) UpdateDraftNote(pid any, mergeRequest, note int, opt *gitlab.UpdateDraftNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.DraftNote, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequest, note, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "UpdateDraftNote", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.DraftNote)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDraftNote indicates an expected call of UpdateDraftNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) UpdateDraftNote(pid, mergeRequest, note, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequest, note, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDraftNote", reflect.TypeOf((*MockClientInterface)(nil).UpdateDraftNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateMergeRequest mocks base method.
|
||||||
|
func (m *MockClientInterface) UpdateMergeRequest(pid any, mergeRequestIID int, opt *gitlab.UpdateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "UpdateMergeRequest", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.MergeRequest)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateMergeRequest indicates an expected call of UpdateMergeRequest.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) UpdateMergeRequest(pid, mergeRequestIID, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateMergeRequest", reflect.TypeOf((*MockClientInterface)(nil).UpdateMergeRequest), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateMergeRequestDiscussionNote mocks base method.
|
||||||
|
func (m *MockClientInterface) UpdateMergeRequestDiscussionNote(pid any, mergeRequestIID int, discussion string, note int, opt *gitlab.UpdateMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, mergeRequestIID, discussion, note, opt}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "UpdateMergeRequestDiscussionNote", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.Note)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateMergeRequestDiscussionNote indicates an expected call of UpdateMergeRequestDiscussionNote.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) UpdateMergeRequestDiscussionNote(pid, mergeRequestIID, discussion, note, opt any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, mergeRequestIID, discussion, note, opt}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateMergeRequestDiscussionNote", reflect.TypeOf((*MockClientInterface)(nil).UpdateMergeRequestDiscussionNote), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadFile mocks base method.
|
||||||
|
func (m *MockClientInterface) UploadFile(pid any, content io.Reader, filename string, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectFile, *gitlab.Response, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{pid, content, filename}
|
||||||
|
for _, a := range options {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "UploadFile", varargs...)
|
||||||
|
ret0, _ := ret[0].(*gitlab.ProjectFile)
|
||||||
|
ret1, _ := ret[1].(*gitlab.Response)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadFile indicates an expected call of UploadFile.
|
||||||
|
func (mr *MockClientInterfaceMockRecorder) UploadFile(pid, content, filename any, options ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{pid, content, filename}, options...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UploadFile", reflect.TypeOf((*MockClientInterface)(nil).UploadFile), varargs...)
|
||||||
|
}
|
||||||
60
cmd/mocks/helpers.go
Normal file
60
cmd/mocks/helpers.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package mock_main
|
||||||
|
|
||||||
|
import (
|
||||||
|
bytes "bytes"
|
||||||
|
io "io"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
gitlab "github.com/xanzy/go-gitlab"
|
||||||
|
gomock "go.uber.org/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
var MergeId = 3
|
||||||
|
|
||||||
|
func NewListMrOptions() *gitlab.ListProjectMergeRequestsOptions {
|
||||||
|
return &gitlab.ListProjectMergeRequestsOptions{
|
||||||
|
Scope: gitlab.Ptr("all"),
|
||||||
|
State: gitlab.Ptr("opened"),
|
||||||
|
SourceBranch: gitlab.Ptr(""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make response makes a simple response value with the right status code */
|
||||||
|
func makeResponse(status int) *gitlab.Response {
|
||||||
|
return &gitlab.Response{
|
||||||
|
Response: &http.Response{
|
||||||
|
StatusCode: status,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockOpts struct {
|
||||||
|
MergeId int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMockClient(t *testing.T) *MockClientInterface {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
mockObj := NewMockClientInterface(ctrl)
|
||||||
|
return mockObj
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a handler to satisfy the withMrs middleware by returning an MR from that endpoint with the given ID */
|
||||||
|
func WithMr(t *testing.T, m *MockClientInterface) *MockClientInterface {
|
||||||
|
options := gitlab.ListProjectMergeRequestsOptions{
|
||||||
|
Scope: gitlab.Ptr("all"),
|
||||||
|
State: gitlab.Ptr("opened"),
|
||||||
|
SourceBranch: gitlab.Ptr(""),
|
||||||
|
}
|
||||||
|
|
||||||
|
m.EXPECT().ListProjectMergeRequests("", &options).Return([]*gitlab.MergeRequest{{IID: MergeId}}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockAttachmentReader struct{}
|
||||||
|
|
||||||
|
func (mf MockAttachmentReader) ReadFile(path string) (io.Reader, error) {
|
||||||
|
return bytes.NewReader([]byte{}), nil
|
||||||
|
}
|
||||||
@@ -30,7 +30,7 @@ type GetPipelineAndJobsResponse struct {
|
|||||||
pipelineHandler fetches information about the current pipeline, and retriggers a pipeline run. For more detailed information
|
pipelineHandler fetches information about the current pipeline, and retriggers a pipeline run. For more detailed information
|
||||||
about a given job in a pipeline, see the jobHandler function
|
about a given job in a pipeline, see the jobHandler function
|
||||||
*/
|
*/
|
||||||
func (a *api) pipelineHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) pipelineHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
a.GetPipelineAndJobs(w, r)
|
a.GetPipelineAndJobs(w, r)
|
||||||
@@ -44,22 +44,23 @@ func (a *api) pipelineHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Gets the latest pipeline for a given commit, returns an error if there is no pipeline */
|
/* Gets the latest pipeline for a given commit, returns an error if there is no pipeline */
|
||||||
func (a *api) GetLastPipeline(commit string) (*gitlab.PipelineInfo, error) {
|
func (a *Api) GetLastPipeline(commit string) (*gitlab.PipelineInfo, error) {
|
||||||
|
|
||||||
l := &gitlab.ListProjectPipelinesOptions{
|
l := &gitlab.ListProjectPipelinesOptions{
|
||||||
SHA: gitlab.Ptr(commit),
|
SHA: gitlab.Ptr(commit),
|
||||||
Sort: gitlab.Ptr("desc"),
|
Sort: gitlab.Ptr("desc"),
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Page = 1
|
pipes, res, err := a.client.ListProjectPipelines(a.projectInfo.ProjectId, l)
|
||||||
l.PerPage = 1
|
|
||||||
|
|
||||||
pipes, _, err := a.client.ListProjectPipelines(a.projectInfo.ProjectId, l)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if res.StatusCode >= 300 {
|
||||||
|
return nil, errors.New("Could not get pipelines")
|
||||||
|
}
|
||||||
|
|
||||||
if len(pipes) == 0 {
|
if len(pipes) == 0 {
|
||||||
return nil, errors.New("No pipeline running or available for commit " + commit)
|
return nil, errors.New("No pipeline running or available for commit " + commit)
|
||||||
}
|
}
|
||||||
@@ -68,13 +69,12 @@ func (a *api) GetLastPipeline(commit string) (*gitlab.PipelineInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Gets the latest pipeline and job information for the current branch */
|
/* Gets the latest pipeline and job information for the current branch */
|
||||||
func (a *api) GetPipelineAndJobs(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) GetPipelineAndJobs(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
commit, err := a.gitInfo.GetLatestCommitOnRemote(a)
|
commit, err := a.gitInfo.GetLatestCommitOnRemote(a)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
|
||||||
handleError(w, err, "Error getting commit on remote branch", http.StatusInternalServerError)
|
handleError(w, err, "Error getting commit on remote branch", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -121,7 +121,7 @@ func (a *api) GetPipelineAndJobs(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *api) RetriggerPipeline(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) RetriggerPipeline(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
id := strings.TrimPrefix(r.URL.Path, "/pipeline/trigger/")
|
id := strings.TrimPrefix(r.URL.Path, "/pipeline/trigger/")
|
||||||
|
|||||||
@@ -1,46 +1,23 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func listPipelineJobs(pid interface{}, pipelineID int, opts *gitlab.ListJobsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Job, *gitlab.Response, error) {
|
var testPipelineId = 12435
|
||||||
return []*gitlab.Job{}, makeResponse(http.StatusOK), nil
|
var testPipelineCommit = "abc123"
|
||||||
}
|
var fakeProjectPipelines = []*gitlab.PipelineInfo{{ID: testPipelineId}}
|
||||||
|
|
||||||
func listPipelineJobsErr(pid interface{}, pipelineID int, opts *gitlab.ListJobsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Job, *gitlab.Response, error) {
|
/* This helps us stub out git interactions that the server would normally run in the project directory */
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
func withGitInfo(a *Api) error {
|
||||||
}
|
a.gitInfo.GetLatestCommitOnRemote = func(a *Api) (string, error) {
|
||||||
|
return testPipelineCommit, nil
|
||||||
func listPipelineJobsNon200(pid interface{}, pipelineID int, opts *gitlab.ListJobsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Job, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func retryPipelineBuild(pid interface{}, pipeline int, options ...gitlab.RequestOptionFunc) (*gitlab.Pipeline, *gitlab.Response, error) {
|
|
||||||
return &gitlab.Pipeline{}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func retryPipelineBuildErr(pid interface{}, pipeline int, options ...gitlab.RequestOptionFunc) (*gitlab.Pipeline, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func retryPipelineBuildNon200(pid interface{}, pipeline int, options ...gitlab.RequestOptionFunc) (*gitlab.Pipeline, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listProjectPipelines(pid interface{}, opt *gitlab.ListProjectPipelinesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.PipelineInfo, *gitlab.Response, error) {
|
|
||||||
return []*gitlab.PipelineInfo{
|
|
||||||
{ID: 12345},
|
|
||||||
}, makeResponse(http.StatusOK), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func withGitInfo(a *api) error {
|
|
||||||
a.gitInfo.GetLatestCommitOnRemote = func(a *api) (string, error) {
|
|
||||||
return "123abc", nil
|
|
||||||
}
|
}
|
||||||
a.gitInfo.BranchName = "some-feature"
|
a.gitInfo.BranchName = "some-feature"
|
||||||
return nil
|
return nil
|
||||||
@@ -48,74 +25,82 @@ func withGitInfo(a *api) error {
|
|||||||
|
|
||||||
func TestPipelineHandler(t *testing.T) {
|
func TestPipelineHandler(t *testing.T) {
|
||||||
t.Run("Gets all pipeline jobs", func(t *testing.T) {
|
t.Run("Gets all pipeline jobs", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().ListProjectPipelines("", gomock.Any()).Return(fakeProjectPipelines, makeResponse(http.StatusOK), nil)
|
||||||
|
client.EXPECT().ListPipelineJobs("", testPipelineId, &gitlab.ListJobsOptions{}).Return([]*gitlab.Job{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/pipeline", nil)
|
request := makeRequest(t, http.MethodGet, "/pipeline", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
server, _ := CreateRouterAndApi(client, withGitInfo)
|
||||||
listPipelineJobs: listPipelineJobs,
|
|
||||||
listProjectPipelines: listProjectPipelines,
|
|
||||||
}, withGitInfo)
|
|
||||||
data := serveRequest(t, server, request, GetPipelineAndJobsResponse{})
|
data := serveRequest(t, server, request, GetPipelineAndJobsResponse{})
|
||||||
|
|
||||||
assert(t, data.SuccessResponse.Message, "Pipeline retrieved")
|
assert(t, data.SuccessResponse.Message, "Pipeline retrieved")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-GET, non-POST methods", func(t *testing.T) {
|
t.Run("Disallows non-GET, non-POST methods", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
request := makeRequest(t, http.MethodPatch, "/pipeline", nil)
|
request := makeRequest(t, http.MethodPatch, "/pipeline", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
server, _ := CreateRouterAndApi(client, withGitInfo)
|
||||||
listPipelineJobs: listPipelineJobs,
|
|
||||||
listProjectPipelines: listProjectPipelines,
|
|
||||||
}, withGitInfo)
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkBadMethod(t, *data, http.MethodGet, http.MethodPost)
|
checkBadMethod(t, *data, http.MethodGet, http.MethodPost)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().ListProjectPipelines("", gomock.Any()).Return(fakeProjectPipelines, makeResponse(http.StatusOK), nil)
|
||||||
|
client.EXPECT().ListPipelineJobs("", testPipelineId, &gitlab.ListJobsOptions{}).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/pipeline", nil)
|
request := makeRequest(t, http.MethodGet, "/pipeline", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
server, _ := CreateRouterAndApi(client, withGitInfo)
|
||||||
listPipelineJobs: listPipelineJobsErr,
|
|
||||||
listProjectPipelines: listProjectPipelines,
|
|
||||||
}, withGitInfo)
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkErrorFromGitlab(t, *data, "Could not get pipeline jobs")
|
checkErrorFromGitlab(t, *data, "Could not get pipeline jobs")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().ListProjectPipelines("", gomock.Any()).Return(fakeProjectPipelines, makeResponse(http.StatusOK), nil)
|
||||||
|
client.EXPECT().ListPipelineJobs("", testPipelineId, &gitlab.ListJobsOptions{}).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodGet, "/pipeline", nil)
|
request := makeRequest(t, http.MethodGet, "/pipeline", nil)
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
server, _ := CreateRouterAndApi(client, withGitInfo)
|
||||||
listPipelineJobs: listPipelineJobsNon200,
|
|
||||||
listProjectPipelines: listProjectPipelines,
|
|
||||||
}, withGitInfo)
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkNon200(t, *data, "Could not get pipeline jobs", "/pipeline")
|
checkNon200(t, *data, "Could not get pipeline jobs", "/pipeline")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
|
||||||
request := makeRequest(t, http.MethodPost, "/pipeline/trigger/1", nil)
|
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
|
||||||
retryPipelineBuild: retryPipelineBuildErr,
|
|
||||||
listProjectPipelines: listProjectPipelines,
|
|
||||||
}, withGitInfo)
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
|
||||||
checkErrorFromGitlab(t, *data, "Could not retrigger pipeline")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Retriggers pipeline", func(t *testing.T) {
|
t.Run("Retriggers pipeline", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/pipeline/trigger/1", nil)
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
client.EXPECT().RetryPipelineBuild("", testPipelineId).Return(&gitlab.Pipeline{}, makeResponse(http.StatusOK), nil)
|
||||||
retryPipelineBuild: retryPipelineBuild,
|
|
||||||
listProjectPipelines: listProjectPipelines,
|
request := makeRequest(t, http.MethodPost, fmt.Sprintf("/pipeline/trigger/%d", testPipelineId), nil)
|
||||||
}, withGitInfo)
|
server, _ := CreateRouterAndApi(client, withGitInfo)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, GetPipelineAndJobsResponse{})
|
data := serveRequest(t, server, request, GetPipelineAndJobsResponse{})
|
||||||
assert(t, data.SuccessResponse.Message, "Pipeline retriggered")
|
assert(t, data.SuccessResponse.Message, "Pipeline retriggered")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client on retrigger", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client on retrigger", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/pipeline/trigger/1", nil)
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{
|
client.EXPECT().RetryPipelineBuild("", testPipelineId).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
retryPipelineBuild: retryPipelineBuildNon200,
|
|
||||||
listProjectPipelines: listProjectPipelines,
|
request := makeRequest(t, http.MethodPost, fmt.Sprintf("/pipeline/trigger/%d", testPipelineId), nil)
|
||||||
}, withGitInfo)
|
server, _ := CreateRouterAndApi(client, withGitInfo)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkNon200(t, *data, "Could not retrigger pipeline", "/pipeline")
|
checkNon200(t, *data, "Could not retrigger pipeline", "/pipeline")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Handles error from Gitlab client on retrigger", func(t *testing.T) {
|
||||||
|
client := mock_main.NewMockClient(t)
|
||||||
|
client.EXPECT().RetryPipelineBuild("", testPipelineId).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, fmt.Sprintf("/pipeline/trigger/%d", testPipelineId), nil)
|
||||||
|
server, _ := CreateRouterAndApi(client, withGitInfo)
|
||||||
|
|
||||||
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
|
checkErrorFromGitlab(t, *data, "Could not retrigger pipeline")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type ReplyResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* replyHandler sends a reply to a note or comment */
|
/* replyHandler sends a reply to a note or comment */
|
||||||
func (a *api) replyHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) replyHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
||||||
|
|||||||
@@ -1,51 +1,80 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
mock_main "gitlab.com/harrisoncramer/gitlab.nvim/cmd/mocks"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addMergeRequestDiscussionNote(pid interface{}, mergeRequest int, discussion string, opt *gitlab.AddMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
var testReplyRequest = ReplyRequest{
|
||||||
return &gitlab.Note{}, makeResponse(http.StatusOK), nil
|
DiscussionId: "abc123",
|
||||||
}
|
Reply: "Some Reply",
|
||||||
|
IsDraft: false,
|
||||||
func addMergeRequestDiscussionNoteErr(pid interface{}, mergeRequest int, discussion string, opt *gitlab.AddMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
|
||||||
return nil, nil, errors.New("Some error from Gitlab")
|
|
||||||
}
|
|
||||||
|
|
||||||
func addMergeRequestDiscussionNoteNon200(pid interface{}, mergeRequest int, discussion string, opt *gitlab.AddMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
|
||||||
return nil, makeResponse(http.StatusSeeOther), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReplyHandler(t *testing.T) {
|
func TestReplyHandler(t *testing.T) {
|
||||||
t.Run("Sends a reply", func(t *testing.T) {
|
t.Run("Sends a reply", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/reply", ReplyRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{addMergeRequestDiscussionNote: addMergeRequestDiscussionNote})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().AddMergeRequestDiscussionNote(
|
||||||
|
"",
|
||||||
|
mock_main.MergeId,
|
||||||
|
testReplyRequest.DiscussionId,
|
||||||
|
gomock.Any(),
|
||||||
|
).Return(&gitlab.Note{}, makeResponse(http.StatusOK), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/reply", testReplyRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ReplyResponse{})
|
data := serveRequest(t, server, request, ReplyResponse{})
|
||||||
assert(t, data.SuccessResponse.Message, "Replied to comment")
|
assert(t, data.SuccessResponse.Message, "Replied to comment")
|
||||||
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
assert(t, data.SuccessResponse.Status, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Disallows non-POST methods", func(t *testing.T) {
|
t.Run("Disallows non-POST methods", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodGet, "/mr/reply", ReplyRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{addMergeRequestDiscussionNote: addMergeRequestDiscussionNote})
|
mock_main.WithMr(t, client)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPut, "/mr/reply", testReplyRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkBadMethod(t, *data, http.MethodPost)
|
checkBadMethod(t, *data, http.MethodPost)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/reply", ReplyRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{addMergeRequestDiscussionNote: addMergeRequestDiscussionNoteErr})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().AddMergeRequestDiscussionNote(
|
||||||
|
"",
|
||||||
|
mock_main.MergeId,
|
||||||
|
testReplyRequest.DiscussionId,
|
||||||
|
gomock.Any(),
|
||||||
|
).Return(nil, nil, errorFromGitlab)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/reply", testReplyRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkErrorFromGitlab(t, *data, "Could not leave reply")
|
checkErrorFromGitlab(t, *data, "Could not leave reply")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
|
||||||
request := makeRequest(t, http.MethodPost, "/mr/reply", ReplyRequest{})
|
client := mock_main.NewMockClient(t)
|
||||||
server, _ := createRouterAndApi(fakeClient{addMergeRequestDiscussionNote: addMergeRequestDiscussionNoteNon200})
|
mock_main.WithMr(t, client)
|
||||||
|
client.EXPECT().AddMergeRequestDiscussionNote(
|
||||||
|
"",
|
||||||
|
mock_main.MergeId,
|
||||||
|
testReplyRequest.DiscussionId,
|
||||||
|
gomock.Any(),
|
||||||
|
).Return(nil, makeResponse(http.StatusSeeOther), nil)
|
||||||
|
|
||||||
|
request := makeRequest(t, http.MethodPost, "/mr/reply", testReplyRequest)
|
||||||
|
server, _ := CreateRouterAndApi(client)
|
||||||
|
|
||||||
data := serveRequest(t, server, request, ErrorResponse{})
|
data := serveRequest(t, server, request, ErrorResponse{})
|
||||||
checkNon200(t, *data, "Could not leave reply", "/mr/reply")
|
checkNon200(t, *data, "Could not leave reply", "/mr/reply")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type DiscussionResolveRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* discussionsResolveHandler sets a discussion to be "resolved" or not resolved, depending on the payload */
|
/* discussionsResolveHandler sets a discussion to be "resolved" or not resolved, depending on the payload */
|
||||||
func (a *api) discussionsResolveHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) discussionsResolveHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodPut {
|
if r.Method != http.MethodPut {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodPut)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPut)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type ReviewersRequestResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* reviewersHandler adds or removes reviewers from an MR */
|
/* reviewersHandler adds or removes reviewers from an MR */
|
||||||
func (a *api) reviewersHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) reviewersHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodPut {
|
if r.Method != http.MethodPut {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodPut)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPut)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type RevisionsResponse struct {
|
|||||||
revisionsHandler gets revision information about the current MR. This data is not used directly but is
|
revisionsHandler gets revision information about the current MR. This data is not used directly but is
|
||||||
a precursor API call for other functionality
|
a precursor API call for other functionality
|
||||||
*/
|
*/
|
||||||
func (a *api) revisionsHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) revisionsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* revokeHandler revokes approval for the current merge request */
|
/* revokeHandler revokes approval for the current merge request */
|
||||||
func (a *api) revokeHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) revokeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodPost)
|
||||||
|
|||||||
@@ -19,24 +19,24 @@ to handle potential shutdown requests and incoming HTTP requests.
|
|||||||
*/
|
*/
|
||||||
func startServer(client *Client, projectInfo *ProjectInfo, gitInfo GitProjectInfo) {
|
func startServer(client *Client, projectInfo *ProjectInfo, gitInfo GitProjectInfo) {
|
||||||
|
|
||||||
m, a := createRouterAndApi(client,
|
m, a := CreateRouterAndApi(client,
|
||||||
func(a *api) error {
|
func(a *Api) error {
|
||||||
a.projectInfo = projectInfo
|
a.projectInfo = projectInfo
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
func(a *api) error {
|
func(a *Api) error {
|
||||||
a.fileReader = attachmentReader{}
|
a.fileReader = attachmentReader{}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
func(a *api) error {
|
func(a *Api) error {
|
||||||
a.gitInfo = &gitInfo
|
a.gitInfo = &gitInfo
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
func(a *api) error {
|
func(a *Api) error {
|
||||||
err := attachEmojisToApi(a)
|
err := attachEmojisToApi(a)
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
func(a *api) error {
|
func(a *Api) error {
|
||||||
a.gitInfo.GetLatestCommitOnRemote = GetLatestCommitOnRemote
|
a.gitInfo.GetLatestCommitOnRemote = GetLatestCommitOnRemote
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -78,13 +78,13 @@ func startServer(client *Client, projectInfo *ProjectInfo, gitInfo GitProjectInf
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The api struct contains common configuration that's accessible to all handlers, such as the gitlab
|
The Api struct contains common configuration that's accessible to all handlers, such as the gitlab
|
||||||
client, the project information, and the channels for signaling error or shutdown requests
|
client, the project information, and the channels for signaling error or shutdown requests
|
||||||
|
|
||||||
The handlers for different Gitlab operations are are all methods on the api struct and interact
|
The handlers for different Gitlab operations are are all methods on the Api struct and interact
|
||||||
with the client value, which is a go-gitlab client.
|
with the client value, which is a go-gitlab client.
|
||||||
*/
|
*/
|
||||||
type api struct {
|
type Api struct {
|
||||||
client ClientInterface
|
client ClientInterface
|
||||||
projectInfo *ProjectInfo
|
projectInfo *ProjectInfo
|
||||||
gitInfo *GitProjectInfo
|
gitInfo *GitProjectInfo
|
||||||
@@ -93,17 +93,17 @@ type api struct {
|
|||||||
sigCh chan os.Signal
|
sigCh chan os.Signal
|
||||||
}
|
}
|
||||||
|
|
||||||
type optFunc func(a *api) error
|
type optFunc func(a *Api) error
|
||||||
|
|
||||||
/*
|
/*
|
||||||
createRouterAndApi wires up the router and attaches all handlers to their respective routes. It also
|
CreateRouterAndApi wires up the router and attaches all handlers to their respective routes. It also
|
||||||
iterates over all option functions to configure API fields such as the project information and default
|
iterates over all option functions to configure API fields such as the project information and default
|
||||||
file reader functionality
|
file reader functionality
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func createRouterAndApi(client ClientInterface, optFuncs ...optFunc) (*http.ServeMux, api) {
|
func CreateRouterAndApi(client ClientInterface, optFuncs ...optFunc) (*http.ServeMux, Api) {
|
||||||
m := http.NewServeMux()
|
m := http.NewServeMux()
|
||||||
a := api{
|
a := Api{
|
||||||
client: client,
|
client: client,
|
||||||
projectInfo: &ProjectInfo{},
|
projectInfo: &ProjectInfo{},
|
||||||
gitInfo: &GitProjectInfo{},
|
gitInfo: &GitProjectInfo{},
|
||||||
@@ -173,11 +173,7 @@ func checkServer(port int) error {
|
|||||||
|
|
||||||
/* Creates a TCP listener on the port specified by the user or a random port */
|
/* Creates a TCP listener on the port specified by the user or a random port */
|
||||||
func createListener() (l net.Listener) {
|
func createListener() (l net.Listener) {
|
||||||
port := os.Args[2]
|
addr := fmt.Sprintf("localhost:%d", pluginOptions.Port)
|
||||||
if port == "" {
|
|
||||||
port = "0"
|
|
||||||
}
|
|
||||||
addr := fmt.Sprintf("localhost:%s", port)
|
|
||||||
l, err := net.Listen("tcp", addr)
|
l, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error starting server: %s\n", err)
|
fmt.Fprintf(os.Stderr, "Error starting server: %s\n", err)
|
||||||
@@ -188,7 +184,7 @@ func createListener() (l net.Listener) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* withMr is a Middlware that gets the current merge request ID and attaches it to the projectInfo */
|
/* withMr is a Middlware that gets the current merge request ID and attaches it to the projectInfo */
|
||||||
func (a *api) withMr(f func(w http.ResponseWriter, r *http.Request)) func(http.ResponseWriter, *http.Request) {
|
func (a *Api) withMr(f func(w http.ResponseWriter, r *http.Request)) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
if a.projectInfo.MergeId != 0 {
|
if a.projectInfo.MergeId != 0 {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ type ShutdownRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* shutdownHandler will shutdown the HTTP server and exit the process by signaling to the shutdown channel */
|
/* shutdownHandler will shutdown the HTTP server and exit the process by signaling to the shutdown channel */
|
||||||
func (a *api) shutdownHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) shutdownHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
w.Header().Set("Allow", http.MethodPost)
|
w.Header().Set("Allow", http.MethodPost)
|
||||||
handleError(w, errors.New("Invalid request type"), "That request type is not allowed", http.StatusMethodNotAllowed)
|
handleError(w, errors.New("Invalid request type"), "That request type is not allowed", http.StatusMethodNotAllowed)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ type SummaryUpdateResponse struct {
|
|||||||
MergeRequest *gitlab.MergeRequest `json:"mr"`
|
MergeRequest *gitlab.MergeRequest `json:"mr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *api) summaryHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) summaryHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
if r.Method != http.MethodPut {
|
if r.Method != http.MethodPut {
|
||||||
|
|||||||
175
cmd/test.go
175
cmd/test.go
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -17,177 +18,7 @@ import (
|
|||||||
The FakeHandlerClient is used to create a fake gitlab client for testing our handlers, where the gitlab APIs are all mocked depending on what is provided during the variable initialization, so that we can simulate different responses from Gitlab
|
The FakeHandlerClient is used to create a fake gitlab client for testing our handlers, where the gitlab APIs are all mocked depending on what is provided during the variable initialization, so that we can simulate different responses from Gitlab
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type fakeClient struct {
|
var errorFromGitlab = errors.New("Some error from Gitlab")
|
||||||
createMrFn func(pid interface{}, opt *gitlab.CreateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)
|
|
||||||
getMergeRequest func(pid interface{}, mergeRequestIID int, opt *gitlab.GetMergeRequestsOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)
|
|
||||||
updateMergeRequest func(pid interface{}, mergeRequestIID int, opt *gitlab.UpdateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)
|
|
||||||
acceptMergeRequest func(pid interface{}, mergeRequestIID int, opt *gitlab.AcceptMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)
|
|
||||||
unapproveMergeRequest func(pid interface{}, mergeRequestIID int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error)
|
|
||||||
uploadFile func(pid interface{}, content io.Reader, filename string, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectFile, *gitlab.Response, error)
|
|
||||||
getMergeRequestDiffVersions func(pid interface{}, mergeRequestIID int, opt *gitlab.GetMergeRequestDiffVersionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiffVersion, *gitlab.Response, error)
|
|
||||||
approveMergeRequest func(pid interface{}, mergeRequestIID int, opt *gitlab.ApproveMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequestApprovals, *gitlab.Response, error)
|
|
||||||
listMergeRequestDiscussions func(pid interface{}, mergeRequestIID int, opt *gitlab.ListMergeRequestDiscussionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Discussion, *gitlab.Response, error)
|
|
||||||
resolveMergeRequestDiscussion func(pid interface{}, mergeRequestIID int, discussion string, opt *gitlab.ResolveMergeRequestDiscussionOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Discussion, *gitlab.Response, error)
|
|
||||||
createMergeRequestDiscussion func(pid interface{}, mergeRequestIID int, opt *gitlab.CreateMergeRequestDiscussionOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Discussion, *gitlab.Response, error)
|
|
||||||
updateMergeRequestDiscussionNote func(pid interface{}, mergeRequestIID int, discussion string, note int, opt *gitlab.UpdateMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error)
|
|
||||||
deleteMergeRequestDiscussionNote func(pid interface{}, mergeRequestIID int, discussion string, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error)
|
|
||||||
addMergeRequestDiscussionNote func(pid interface{}, mergeRequestIID int, discussion string, opt *gitlab.AddMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error)
|
|
||||||
listAllProjectMembers func(pid interface{}, opt *gitlab.ListProjectMembersOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectMember, *gitlab.Response, error)
|
|
||||||
retryPipelineBuild func(pid interface{}, pipeline int, options ...gitlab.RequestOptionFunc) (*gitlab.Pipeline, *gitlab.Response, error)
|
|
||||||
listPipelineJobs func(pid interface{}, pipelineID int, opts *gitlab.ListJobsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Job, *gitlab.Response, error)
|
|
||||||
listProjectPipelines func(pid interface{}, opt *gitlab.ListProjectPipelinesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.PipelineInfo, *gitlab.Response, error)
|
|
||||||
getTraceFile func(pid interface{}, jobID int, options ...gitlab.RequestOptionFunc) (*bytes.Reader, *gitlab.Response, error)
|
|
||||||
listLabels func(pid interface{}, opt *gitlab.ListLabelsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Label, *gitlab.Response, error)
|
|
||||||
listMergeRequestAwardEmojiOnNote func(pid interface{}, mergeRequestIID, noteID int, opt *gitlab.ListAwardEmojiOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.AwardEmoji, *gitlab.Response, error)
|
|
||||||
deleteMergeRequestAwardEmojiOnNote func(pid interface{}, mergeRequestIID, noteID, awardID int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error)
|
|
||||||
currentUser func(options ...gitlab.RequestOptionFunc) (*gitlab.User, *gitlab.Response, error)
|
|
||||||
createDraftNote func(pid interface{}, mergeRequestIID int, opt *gitlab.CreateDraftNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.DraftNote, *gitlab.Response, error)
|
|
||||||
listDraftNotes func(pid interface{}, mergeRequest int, opt *gitlab.ListDraftNotesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.DraftNote, *gitlab.Response, error)
|
|
||||||
deleteDraftNote func(pid interface{}, mergeRequest int, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error)
|
|
||||||
updateDraftNote func(pid interface{}, mergeRequest int, note int, opt *gitlab.UpdateDraftNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.DraftNote, *gitlab.Response, error)
|
|
||||||
publishAllDraftNotes func(pid interface{}, mergeRequest int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error)
|
|
||||||
publishDraftNote func(pid interface{}, mergeRequest int, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error)
|
|
||||||
listProjectMergeRequests func(pid interface{}, opt *gitlab.ListProjectMergeRequestsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequest, *gitlab.Response, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Author struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
State string `json:"state"`
|
|
||||||
AvatarURL string `json:"avatar_url"`
|
|
||||||
WebURL string `json:"web_url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) CreateMergeRequest(pid interface{}, opt *gitlab.CreateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return f.createMrFn(pid, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) AcceptMergeRequest(pid interface{}, mergeRequestIID int, opt *gitlab.AcceptMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return f.acceptMergeRequest(pid, mergeRequestIID, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) GetMergeRequest(pid interface{}, mergeRequestIID int, opt *gitlab.GetMergeRequestsOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return f.getMergeRequest(pid, mergeRequestIID, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) UpdateMergeRequest(pid interface{}, mergeRequestIID int, opt *gitlab.UpdateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
return f.updateMergeRequest(pid, mergeRequestIID, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) UnapproveMergeRequest(pid interface{}, mergeRequestIID int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return f.unapproveMergeRequest(pid, mergeRequestIID, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) UploadFile(pid interface{}, content io.Reader, filename string, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectFile, *gitlab.Response, error) {
|
|
||||||
return f.uploadFile(pid, content, filename, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) GetMergeRequestDiffVersions(pid interface{}, mergeRequestIID int, opt *gitlab.GetMergeRequestDiffVersionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiffVersion, *gitlab.Response, error) {
|
|
||||||
return f.getMergeRequestDiffVersions(pid, mergeRequestIID, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) ApproveMergeRequest(pid interface{}, mergeRequestIID int, opt *gitlab.ApproveMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequestApprovals, *gitlab.Response, error) {
|
|
||||||
return f.approveMergeRequest(pid, mergeRequestIID, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) ListMergeRequestDiscussions(pid interface{}, mergeRequestIID int, opt *gitlab.ListMergeRequestDiscussionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Discussion, *gitlab.Response, error) {
|
|
||||||
return f.listMergeRequestDiscussions(pid, mergeRequestIID, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) ResolveMergeRequestDiscussion(pid interface{}, mergeRequestIID int, discussion string, opt *gitlab.ResolveMergeRequestDiscussionOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Discussion, *gitlab.Response, error) {
|
|
||||||
return f.resolveMergeRequestDiscussion(pid, mergeRequestIID, discussion, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) CreateMergeRequestDiscussion(pid interface{}, mergeRequestIID int, opt *gitlab.CreateMergeRequestDiscussionOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Discussion, *gitlab.Response, error) {
|
|
||||||
return f.createMergeRequestDiscussion(pid, mergeRequestIID, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) UpdateMergeRequestDiscussionNote(pid interface{}, mergeRequestIID int, discussion string, note int, opt *gitlab.UpdateMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
|
||||||
return f.updateMergeRequestDiscussionNote(pid, mergeRequestIID, discussion, note, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) DeleteMergeRequestDiscussionNote(pid interface{}, mergeRequestIID int, discussion string, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return f.deleteMergeRequestDiscussionNote(pid, mergeRequestIID, discussion, note, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) AddMergeRequestDiscussionNote(pid interface{}, mergeRequestIID int, discussion string, opt *gitlab.AddMergeRequestDiscussionNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) {
|
|
||||||
return f.addMergeRequestDiscussionNote(pid, mergeRequestIID, discussion, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) ListAllProjectMembers(pid interface{}, opt *gitlab.ListProjectMembersOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectMember, *gitlab.Response, error) {
|
|
||||||
return f.listAllProjectMembers(pid, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) RetryPipelineBuild(pid interface{}, pipeline int, options ...gitlab.RequestOptionFunc) (*gitlab.Pipeline, *gitlab.Response, error) {
|
|
||||||
return f.retryPipelineBuild(pid, pipeline, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) ListPipelineJobs(pid interface{}, pipelineID int, opts *gitlab.ListJobsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Job, *gitlab.Response, error) {
|
|
||||||
return f.listPipelineJobs(pid, pipelineID, opts, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) ListProjectPipelines(pid interface{}, opt *gitlab.ListProjectPipelinesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.PipelineInfo, *gitlab.Response, error) {
|
|
||||||
return f.listProjectPipelines(pid, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) GetTraceFile(pid interface{}, jobID int, options ...gitlab.RequestOptionFunc) (*bytes.Reader, *gitlab.Response, error) {
|
|
||||||
return f.getTraceFile(pid, jobID, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) ListLabels(pid interface{}, opt *gitlab.ListLabelsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Label, *gitlab.Response, error) {
|
|
||||||
return f.listLabels(pid, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) ListMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID int, noteID int, opt *gitlab.ListAwardEmojiOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.AwardEmoji, *gitlab.Response, error) {
|
|
||||||
return f.listMergeRequestAwardEmojiOnNote(pid, mergeRequestIID, noteID, opt, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) DeleteMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID, awardID int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return f.deleteMergeRequestAwardEmojiOnNote(pid, mergeRequestIID, noteID, awardID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) CreateDraftNote(pid interface{}, mergeRequestIID int, opt *gitlab.CreateDraftNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.DraftNote, *gitlab.Response, error) {
|
|
||||||
return f.createDraftNote(pid, mergeRequestIID, opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) ListDraftNotes(pid interface{}, mergeRequestIID int, opt *gitlab.ListDraftNotesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.DraftNote, *gitlab.Response, error) {
|
|
||||||
return f.listDraftNotes(pid, mergeRequestIID, opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) CurrentUser(options ...gitlab.RequestOptionFunc) (*gitlab.User, *gitlab.Response, error) {
|
|
||||||
return f.currentUser()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) CreateMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID int, opt *gitlab.CreateAwardEmojiOptions, options ...gitlab.RequestOptionFunc) (*gitlab.AwardEmoji, *gitlab.Response, error) {
|
|
||||||
return &gitlab.AwardEmoji{}, &gitlab.Response{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) UpdateDraftNote(pid interface{}, mergeRequest int, note int, opt *gitlab.UpdateDraftNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.DraftNote, *gitlab.Response, error) {
|
|
||||||
return f.updateDraftNote(pid, mergeRequest, note, opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) DeleteDraftNote(pid interface{}, mergeRequestIID int, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return f.deleteDraftNote(pid, mergeRequestIID, note)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) PublishDraftNote(pid interface{}, mergeRequest int, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return f.publishDraftNote(pid, mergeRequest, note)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f fakeClient) PublishAllDraftNotes(pid interface{}, mergeRequest int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) {
|
|
||||||
return f.publishAllDraftNotes(pid, mergeRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This middleware function needs to return an ID for the rest of the handlers */
|
|
||||||
func (f fakeClient) ListProjectMergeRequests(pid interface{}, opt *gitlab.ListProjectMergeRequestsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequest, *gitlab.Response, error) {
|
|
||||||
if f.listProjectMergeRequests == nil {
|
|
||||||
return []*gitlab.MergeRequest{{ID: 1}}, &gitlab.Response{}, nil
|
|
||||||
} else {
|
|
||||||
return f.listProjectMergeRequests(pid, opt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The assert function is a helper function used to check two comparables */
|
/* The assert function is a helper function used to check two comparables */
|
||||||
func assert[T comparable](t *testing.T, got T, want T) {
|
func assert[T comparable](t *testing.T, got T, want T) {
|
||||||
@@ -247,7 +78,7 @@ func checkErrorFromGitlab(t *testing.T, data ErrorResponse, msg string) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
assert(t, data.Status, http.StatusInternalServerError)
|
assert(t, data.Status, http.StatusInternalServerError)
|
||||||
assert(t, data.Message, msg)
|
assert(t, data.Message, msg)
|
||||||
assert(t, data.Details, "Some error from Gitlab")
|
assert(t, data.Details, errorFromGitlab.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkBadMethod(t *testing.T, data ErrorResponse, methods ...string) {
|
func checkBadMethod(t *testing.T, data ErrorResponse, methods ...string) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ type UserResponse struct {
|
|||||||
User *gitlab.User `json:"user"`
|
User *gitlab.User `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *api) meHandler(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) meHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
|
||||||
|
|||||||
@@ -55,10 +55,6 @@ QUICK START *gitlab.nvim.quick-start*
|
|||||||
|
|
||||||
This will checkout the branch locally, and up the plugin's reviewer pane.
|
This will checkout the branch locally, and up the plugin's reviewer pane.
|
||||||
|
|
||||||
NOTE: At the moment, the plugin assumes that the remote where you want to
|
|
||||||
merge your feature branch is called "origin".
|
|
||||||
|
|
||||||
|
|
||||||
INSTALLATION *gitlab.nvim.installation*
|
INSTALLATION *gitlab.nvim.installation*
|
||||||
|
|
||||||
With Lazy:
|
With Lazy:
|
||||||
@@ -165,6 +161,7 @@ you call this function with no values the defaults will be used:
|
|||||||
},
|
},
|
||||||
connection_settings = {
|
connection_settings = {
|
||||||
insecure = false, -- Like curl's --insecure option, ignore bad x509 certificates on connection
|
insecure = false, -- Like curl's --insecure option, ignore bad x509 certificates on connection
|
||||||
|
remote = "origin", -- The default remote that your MRs target
|
||||||
},
|
},
|
||||||
keymaps = {
|
keymaps = {
|
||||||
disable_all = false, -- Disable all mappings created by the plugin
|
disable_all = false, -- Disable all mappings created by the plugin
|
||||||
@@ -685,8 +682,11 @@ following to your config:
|
|||||||
|
|
||||||
TROUBLESHOOTING *gitlab.nvim.troubleshooting*
|
TROUBLESHOOTING *gitlab.nvim.troubleshooting*
|
||||||
|
|
||||||
To check that the current settings of the plugin are configured correctly,~
|
To check the health of the plugin and related dependencies, please run:
|
||||||
please run:~
|
>vim
|
||||||
|
:checkhealth gitlab
|
||||||
|
<
|
||||||
|
To print your current settings:
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").print_settings()
|
require("gitlab").print_settings()
|
||||||
<
|
<
|
||||||
@@ -726,17 +726,24 @@ default arguments outlined under "Configuring the Plugin".
|
|||||||
gitlab.choose_merge_request({opts}) ~
|
gitlab.choose_merge_request({opts}) ~
|
||||||
|
|
||||||
Choose a merge request from a list of those open in your current project to
|
Choose a merge request from a list of those open in your current project to
|
||||||
review. This command will automatically check out the feature branch locally,
|
review. This command will automatically check out the feature branch locally
|
||||||
and by default also open the reviewer pane (this can be overridden with the
|
and open the reviewer pane (this can be overridden with the `open_reviewer`
|
||||||
`open_reviewer` parameter).
|
parameter.
|
||||||
|
You can also filter merge requests by specifying `label` and `notlabel`
|
||||||
|
parameters.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").choose_merge_request()
|
require("gitlab").choose_merge_request()
|
||||||
require("gitlab").choose_merge_request({ open_reviewer = false })
|
require("gitlab").choose_merge_request({ open_reviewer = false })
|
||||||
|
require("gitlab").choose_merge_request({ label = {"include_mrs_with_label"} })
|
||||||
|
require("gitlab").choose_merge_request({ notlabel = {"exclude_mrs_with_label"} })
|
||||||
<
|
<
|
||||||
Parameters: ~
|
Parameters: ~
|
||||||
• {opts}: (table|nil) Keyword arguments to configure the checkout.
|
• {opts}: (table|nil) Keyword arguments to configure the checkout.
|
||||||
• {open_reviewer}: (boolean) Whether to open the reviewer after
|
• {open_reviewer}: (boolean) Whether to open the reviewer after
|
||||||
switching branches. True by default.
|
switching branches. True by default.
|
||||||
|
• {label}: (table<string>) Return merge requests with *including* matching labels
|
||||||
|
• {notlabel}: (table<string>) Return merge requests *excluding*
|
||||||
|
matching label
|
||||||
<
|
<
|
||||||
*gitlab.nvim.review*
|
*gitlab.nvim.review*
|
||||||
gitlab.review() ~
|
gitlab.review() ~
|
||||||
|
|||||||
36
example.lua
36
example.lua
@@ -1,36 +0,0 @@
|
|||||||
local Layout = require("nui.layout")
|
|
||||||
local Popup = require("nui.popup")
|
|
||||||
|
|
||||||
local opts = {
|
|
||||||
buf_options = {
|
|
||||||
filetype = "markdown",
|
|
||||||
},
|
|
||||||
focusable = true,
|
|
||||||
border = {
|
|
||||||
style = "rounded",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
local title_popup = Popup(opts)
|
|
||||||
local description_popup = Popup(opts)
|
|
||||||
local info_popup = Popup(opts)
|
|
||||||
|
|
||||||
local layout = Layout(
|
|
||||||
{
|
|
||||||
position = "50%",
|
|
||||||
relative = "editor",
|
|
||||||
size = {
|
|
||||||
width = "95%",
|
|
||||||
height = "95%",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Layout.Box({
|
|
||||||
Layout.Box(title_popup, { size = { height = 3 } }),
|
|
||||||
Layout.Box({
|
|
||||||
Layout.Box(description_popup, { grow = 1 }),
|
|
||||||
Layout.Box(info_popup, { size = { height = 15 } }),
|
|
||||||
}, { dir = "col", size = "100%" }),
|
|
||||||
}, { dir = "col" })
|
|
||||||
)
|
|
||||||
|
|
||||||
layout:mount()
|
|
||||||
4
go.mod
4
go.mod
@@ -11,9 +11,13 @@ require (
|
|||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
|
go.uber.org/mock v0.4.0 // indirect
|
||||||
|
golang.org/x/mod v0.11.0 // indirect
|
||||||
golang.org/x/net v0.8.0 // indirect
|
golang.org/x/net v0.8.0 // indirect
|
||||||
golang.org/x/oauth2 v0.6.0 // indirect
|
golang.org/x/oauth2 v0.6.0 // indirect
|
||||||
|
golang.org/x/sys v0.6.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/protobuf v1.29.1 // indirect
|
google.golang.org/protobuf v1.29.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
8
go.sum
8
go.sum
@@ -21,18 +21,26 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
github.com/xanzy/go-gitlab v0.102.0 h1:ExHuJ1OTQ2yt25zBMMj0G96ChBirGYv8U7HyUiYkZ+4=
|
github.com/xanzy/go-gitlab v0.102.0 h1:ExHuJ1OTQ2yt25zBMMj0G96ChBirGYv8U7HyUiYkZ+4=
|
||||||
github.com/xanzy/go-gitlab v0.102.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
|
github.com/xanzy/go-gitlab v0.102.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
|
||||||
|
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||||
|
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||||
|
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
|
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
|
||||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||||
|
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
---@meta diagnostics
|
|
||||||
|
|
||||||
---@class Author
|
|
||||||
---@field id integer
|
|
||||||
---@field username string
|
|
||||||
---@field email string
|
|
||||||
---@field name string
|
|
||||||
---@field state string
|
|
||||||
---@field avatar_url string
|
|
||||||
---@field web_url string
|
|
||||||
|
|
||||||
---@class LinePosition
|
|
||||||
---@field line_code string
|
|
||||||
---@field type string
|
|
||||||
|
|
||||||
---@class GitlabLineRange
|
|
||||||
---@field start LinePosition
|
|
||||||
---@field end LinePosition
|
|
||||||
|
|
||||||
---@class NotePosition
|
|
||||||
---@field base_sha string
|
|
||||||
---@field start_sha string
|
|
||||||
---@field head_sha string
|
|
||||||
---@field position_type string
|
|
||||||
---@field new_path string?
|
|
||||||
---@field new_line integer?
|
|
||||||
---@field old_path string?
|
|
||||||
---@field old_line integer?
|
|
||||||
---@field line_range GitlabLineRange?
|
|
||||||
|
|
||||||
---@class Note
|
|
||||||
---@field id integer
|
|
||||||
---@field type string
|
|
||||||
---@field body string
|
|
||||||
---@field attachment string
|
|
||||||
---@field title string
|
|
||||||
---@field file_name string
|
|
||||||
---@field author Author
|
|
||||||
---@field system boolean
|
|
||||||
---@field expires_at string?
|
|
||||||
---@field updated_at string?
|
|
||||||
---@field created_at string?
|
|
||||||
---@field noteable_id integer
|
|
||||||
---@field noteable_type string
|
|
||||||
---@field commit_id string
|
|
||||||
---@field position NotePosition
|
|
||||||
---@field resolvable boolean
|
|
||||||
---@field resolved boolean
|
|
||||||
---@field resolved_by Author
|
|
||||||
---@field resolved_at string?
|
|
||||||
---@field noteable_iid integer
|
|
||||||
---@field url string?
|
|
||||||
|
|
||||||
---@class UnlinkedNote: Note
|
|
||||||
---@field position nil
|
|
||||||
|
|
||||||
---@class Discussion
|
|
||||||
---@field id string
|
|
||||||
---@field individual_note boolean
|
|
||||||
---@field notes Note[]
|
|
||||||
|
|
||||||
---@class UnlinkedDiscussion: Discussion
|
|
||||||
---@field notes UnlinkedNote[]
|
|
||||||
|
|
||||||
---@class DiscussionData
|
|
||||||
---@field discussions Discussion[]
|
|
||||||
---@field unlinked_discussions UnlinkedDiscussion[]
|
|
||||||
|
|
||||||
---@class EmojiMap: table<string, Emoji>
|
|
||||||
---@class Emoji
|
|
||||||
---@field unicode string
|
|
||||||
---@field unicodeAlternates string[]
|
|
||||||
---@field name string
|
|
||||||
---@field shortname string
|
|
||||||
---@field category string
|
|
||||||
---@field aliases string[]
|
|
||||||
---@field aliasesASCII string[]
|
|
||||||
---@field keywords string[]
|
|
||||||
---@field moji string
|
|
||||||
|
|
||||||
---@class WinbarTable
|
|
||||||
---@field view_type string
|
|
||||||
---@field resolvable_discussions number
|
|
||||||
---@field resolved_discussions number
|
|
||||||
---@field inline_draft_notes number
|
|
||||||
---@field unlinked_draft_notes number
|
|
||||||
---@field resolvable_notes number
|
|
||||||
---@field resolved_notes number
|
|
||||||
---@field help_keymap string
|
|
||||||
---
|
|
||||||
---@class SignTable
|
|
||||||
---@field name string
|
|
||||||
---@field group string
|
|
||||||
---@field priority number
|
|
||||||
---@field id number
|
|
||||||
---@field lnum number
|
|
||||||
---@field buffer number?
|
|
||||||
---
|
|
||||||
---@class DiagnosticTable
|
|
||||||
---@field message string
|
|
||||||
---@field col number
|
|
||||||
---@field severity number
|
|
||||||
---@field user_data table
|
|
||||||
---@field source string
|
|
||||||
---@field code string?
|
|
||||||
|
|
||||||
---@class LineRange
|
|
||||||
---@field start_line integer
|
|
||||||
---@field end_line integer
|
|
||||||
|
|
||||||
---@class DiffviewInfo
|
|
||||||
---@field modification_type string
|
|
||||||
---@field file_name string
|
|
||||||
---@field current_bufnr integer
|
|
||||||
---@field new_sha_win_id integer
|
|
||||||
---@field old_sha_win_id integer
|
|
||||||
---@field opposite_bufnr integer
|
|
||||||
---@field new_line_from_buf integer
|
|
||||||
---@field old_line_from_buf integer
|
|
||||||
|
|
||||||
---@class LocationData
|
|
||||||
---@field old_line integer | nil
|
|
||||||
---@field new_line integer | nil
|
|
||||||
---@field line_range ReviewerRangeInfo|nil
|
|
||||||
|
|
||||||
---@class DraftNote
|
|
||||||
---@field note string
|
|
||||||
---@field id integer
|
|
||||||
---@field author_id integer
|
|
||||||
---@field merge_request_id integer
|
|
||||||
---@field resolve_discussion boolean
|
|
||||||
---@field discussion_id string -- This will always be ""
|
|
||||||
---@field commit_id string -- This will always be ""
|
|
||||||
---@field line_code string
|
|
||||||
---@field position NotePosition
|
|
||||||
@@ -4,11 +4,13 @@ local git = require("gitlab.git")
|
|||||||
local u = require("gitlab.utils")
|
local u = require("gitlab.utils")
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
---@class SwitchOpts
|
---@class ChooseMergeRequestOptions
|
||||||
---@field open_reviewer boolean
|
---@field open_reviewer? boolean
|
||||||
|
---@field label? string[]
|
||||||
|
---@field notlabel? string[]
|
||||||
|
|
||||||
---Opens up a select menu that lets you choose a different merge request.
|
---Opens up a select menu that lets you choose a different merge request.
|
||||||
---@param opts SwitchOpts|nil
|
---@param opts ChooseMergeRequestOptions|nil
|
||||||
M.choose_merge_request = function(opts)
|
M.choose_merge_request = function(opts)
|
||||||
local has_clean_tree, clean_tree_err = git.has_clean_tree()
|
local has_clean_tree, clean_tree_err = git.has_clean_tree()
|
||||||
if clean_tree_err ~= nil then
|
if clean_tree_err ~= nil then
|
||||||
|
|||||||
341
lua/gitlab/annotations.lua
Normal file
341
lua/gitlab/annotations.lua
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
---@meta diagnostics
|
||||||
|
|
||||||
|
---@alias BorderEnum "rounded" | "single" | "double" | "solid"
|
||||||
|
---@alias SeverityEnum "ERROR" | "WARN" | "INFO" | "HINT"
|
||||||
|
|
||||||
|
---@class Author
|
||||||
|
---@field id integer
|
||||||
|
---@field username string
|
||||||
|
---@field email string
|
||||||
|
---@field name string
|
||||||
|
---@field state string
|
||||||
|
---@field avatar_url string
|
||||||
|
---@field web_url string
|
||||||
|
|
||||||
|
---@class LinePosition
|
||||||
|
---@field line_code string
|
||||||
|
---@field type string
|
||||||
|
|
||||||
|
---@class GitlabLineRange
|
||||||
|
---@field start LinePosition
|
||||||
|
---@field end LinePosition
|
||||||
|
|
||||||
|
---@class NotePosition
|
||||||
|
---@field base_sha string
|
||||||
|
---@field start_sha string
|
||||||
|
---@field head_sha string
|
||||||
|
---@field position_type string
|
||||||
|
---@field new_path string?
|
||||||
|
---@field new_line integer?
|
||||||
|
---@field old_path string?
|
||||||
|
---@field old_line integer?
|
||||||
|
---@field line_range GitlabLineRange?
|
||||||
|
|
||||||
|
---@class Note
|
||||||
|
---@field id integer
|
||||||
|
---@field type string
|
||||||
|
---@field body string
|
||||||
|
---@field attachment string
|
||||||
|
---@field title string
|
||||||
|
---@field file_name string
|
||||||
|
---@field author Author
|
||||||
|
---@field system boolean
|
||||||
|
---@field expires_at string?
|
||||||
|
---@field updated_at string?
|
||||||
|
---@field created_at string?
|
||||||
|
---@field noteable_id integer
|
||||||
|
---@field noteable_type string
|
||||||
|
---@field commit_id string
|
||||||
|
---@field position NotePosition
|
||||||
|
---@field resolvable boolean
|
||||||
|
---@field resolved boolean
|
||||||
|
---@field resolved_by Author
|
||||||
|
---@field resolved_at string?
|
||||||
|
---@field noteable_iid integer
|
||||||
|
---@field url string?
|
||||||
|
|
||||||
|
---@class UnlinkedNote: Note
|
||||||
|
---@field position nil
|
||||||
|
|
||||||
|
---@class Discussion
|
||||||
|
---@field id string
|
||||||
|
---@field individual_note boolean
|
||||||
|
---@field notes Note[]
|
||||||
|
|
||||||
|
---@class UnlinkedDiscussion: Discussion
|
||||||
|
---@field notes UnlinkedNote[]
|
||||||
|
|
||||||
|
---@class DiscussionData
|
||||||
|
---@field discussions Discussion[]
|
||||||
|
---@field unlinked_discussions UnlinkedDiscussion[]
|
||||||
|
|
||||||
|
---@class EmojiMap: table<string, Emoji>
|
||||||
|
---@class Emoji
|
||||||
|
---@field unicode string
|
||||||
|
---@field unicodeAlternates string[]
|
||||||
|
---@field name string
|
||||||
|
---@field shortname string
|
||||||
|
---@field category string
|
||||||
|
---@field aliases string[]
|
||||||
|
---@field aliasesASCII string[]
|
||||||
|
---@field keywords string[]
|
||||||
|
---@field moji string
|
||||||
|
|
||||||
|
---@class WinbarTable
|
||||||
|
---@field view_type string
|
||||||
|
---@field resolvable_discussions number
|
||||||
|
---@field resolved_discussions number
|
||||||
|
---@field inline_draft_notes number
|
||||||
|
---@field unlinked_draft_notes number
|
||||||
|
---@field resolvable_notes number
|
||||||
|
---@field resolved_notes number
|
||||||
|
---@field help_keymap string
|
||||||
|
---
|
||||||
|
---@class SignTable
|
||||||
|
---@field name string
|
||||||
|
---@field group string
|
||||||
|
---@field priority number
|
||||||
|
---@field id number
|
||||||
|
---@field lnum number
|
||||||
|
---@field buffer number?
|
||||||
|
---
|
||||||
|
---@class DiagnosticTable
|
||||||
|
---@field message string
|
||||||
|
---@field col number
|
||||||
|
---@field severity number
|
||||||
|
---@field user_data table
|
||||||
|
---@field source string
|
||||||
|
---@field code string?
|
||||||
|
|
||||||
|
---@class LineRange
|
||||||
|
---@field start_line integer
|
||||||
|
---@field end_line integer
|
||||||
|
|
||||||
|
---@class DiffviewInfo
|
||||||
|
---@field modification_type string
|
||||||
|
---@field file_name string
|
||||||
|
---@field current_bufnr integer
|
||||||
|
---@field new_sha_win_id integer
|
||||||
|
---@field old_sha_win_id integer
|
||||||
|
---@field opposite_bufnr integer
|
||||||
|
---@field new_line_from_buf integer
|
||||||
|
---@field old_line_from_buf integer
|
||||||
|
|
||||||
|
---@class LocationData
|
||||||
|
---@field old_line integer | nil
|
||||||
|
---@field new_line integer | nil
|
||||||
|
---@field line_range ReviewerRangeInfo|nil
|
||||||
|
|
||||||
|
---@class DraftNote
|
||||||
|
---@field note string
|
||||||
|
---@field id integer
|
||||||
|
---@field author_id integer
|
||||||
|
---@field merge_request_id integer
|
||||||
|
---@field resolve_discussion boolean
|
||||||
|
---@field discussion_id string -- This will always be ""
|
||||||
|
---@field commit_id string -- This will always be ""
|
||||||
|
---@field line_code string
|
||||||
|
---@field position NotePosition
|
||||||
|
---
|
||||||
|
---
|
||||||
|
--- Plugin Settings
|
||||||
|
---
|
||||||
|
---@class Settings
|
||||||
|
---@field port? number -- The port of the Go server, which runs in the background, if omitted or `nil` the port will be chosen automatically
|
||||||
|
---@field remote_branch "origin" | string -- The remote, "origin" by default
|
||||||
|
---@field log_path? string -- Log path for the Go server
|
||||||
|
---@field string? any -- Custom path for `.gitlab.nvim` file, please read the "Connecting to Gitlab" section
|
||||||
|
---@field debug? DebugSettings -- Which values to log
|
||||||
|
---@field attachment_dir? string, -- The local directory for files (see the "summary" section)
|
||||||
|
---@field reviewer_settings? ReviewerSettings -- Settings for the reviewer view
|
||||||
|
---@field connection_settings? ConnectionSettings -- Settings for the connection to Gitlab
|
||||||
|
---@field keymaps? Keymaps -- Keymaps for the plugin
|
||||||
|
---@field popup? PopupSettings -- Settings for the popup windows
|
||||||
|
---@field discussion_tree? DiscussionSettings -- Settings for the popup windows
|
||||||
|
---@field choose_merge_request? ChooseMergeRequestSettings -- Default settings when choosing a merge request
|
||||||
|
---@field info? InfoSettings -- Settings for the "info" or "summary" view
|
||||||
|
---@field discussion_signs? DiscussionSigns -- The settings for discussion signs/diagnostics
|
||||||
|
---@field pipeline? PipelineSettings -- The settings for the pipeline popup
|
||||||
|
---@field create_mr? CreateMrSettings -- The settings when creating an MR
|
||||||
|
---@field colors? ColorSettings --- Colors settings for the plugin
|
||||||
|
|
||||||
|
---@class DiscussionSigns: table
|
||||||
|
---@field enabled? boolean -- Show diagnostics for gitlab comments in the reviewer
|
||||||
|
---@field skip_resolved_discussion? boolean -- Show diagnostics for resolved discussions
|
||||||
|
---@field severity? SeverityEnum
|
||||||
|
---@field virtual_text? boolean -- Whether to show the comment text inline as floating virtual text
|
||||||
|
---@field use_diagnostic_signs? boolean -- Show diagnostic sign (depending on the `severity` setting) along with the comment icon
|
||||||
|
---@field priority? number -- Higher will override LSP warnings, etc
|
||||||
|
---@field icons? IconsOpts -- Customize the icons shown with comments or notes
|
||||||
|
|
||||||
|
---@class ColorSettings: table
|
||||||
|
---@field discussion_tree? DiscussionTreeColors -- Colors for elements in the discussion tree
|
||||||
|
|
||||||
|
---@class DiscussionTreeColors
|
||||||
|
--- @field username? string
|
||||||
|
--- @field mention? string
|
||||||
|
--- @field date? string
|
||||||
|
--- @field expander? string
|
||||||
|
--- @field directory? string
|
||||||
|
--- @field directory_icon? string
|
||||||
|
--- @field file_name? string
|
||||||
|
--- @field resolved? string
|
||||||
|
--- @field unresolved? string
|
||||||
|
--- @field draft? string
|
||||||
|
|
||||||
|
---@class CreateMrSettings: table
|
||||||
|
---@field target? string -- Default branch to target when creating an MR
|
||||||
|
---@field template_file? string -- Default MR template in .gitlab/merge_request_templates
|
||||||
|
---@field delete_branch? boolean -- Whether the source branch will be marked for deletion
|
||||||
|
---@field squash? boolean -- Whether the commits will be marked for squashing
|
||||||
|
---@field title_input? TitleInputSettings
|
||||||
|
---@field fork? ForkSettings
|
||||||
|
|
||||||
|
---@class ForkSettings: table
|
||||||
|
---@field enabled? boolean -- If making an MR from a fork
|
||||||
|
---@field forked_project_id? number -- The Gitlab ID of the project you are merging into. If nil, will be prompted.
|
||||||
|
|
||||||
|
---@class TitleInputSettings: table
|
||||||
|
---@field width? number
|
||||||
|
---@field border? BorderEnum
|
||||||
|
|
||||||
|
---@class PipelineSettings: table
|
||||||
|
---@field created? string -- What to show for this pipeline status, by default "",
|
||||||
|
---@field pending? string -- What to show for this pipeline status, by default "",
|
||||||
|
---@field preparing? string -- What to show for this pipeline status, by default "",
|
||||||
|
---@field scheduled? string -- What to show for this pipeline status, by default "",
|
||||||
|
---@field running? string -- What to show for this pipeline status, by default "",
|
||||||
|
---@field canceled? string -- What to show for this pipeline status, by default "↪",
|
||||||
|
---@field skipped? string -- What to show for this pipeline status, by default "↪",
|
||||||
|
---@field success? string -- What to show for this pipeline status, by default "✓",
|
||||||
|
---@field failed? string -- What to show for this pipeline status, by default "",
|
||||||
|
|
||||||
|
---@class IconsOpts: table
|
||||||
|
---@field comment? string -- The icon for comments, by default "→|",
|
||||||
|
---@field range? string -- The icon for lines in ranged comments, by default " |"
|
||||||
|
|
||||||
|
---@class ReviewerSettings: table
|
||||||
|
---@field diffview? SettingsDiffview -- Settings for diffview (the dependency)
|
||||||
|
|
||||||
|
---@class SettingsDiffview: table
|
||||||
|
---@field imply_local? boolean -- If true, will attempt to use --imply_local option when calling |:DiffviewOpen|
|
||||||
|
|
||||||
|
---@class ConnectionSettings: table
|
||||||
|
---@field insecure? boolean -- Like curl's --insecure option, ignore bad x509 certificates on connection
|
||||||
|
|
||||||
|
---@class DebugSettings: table
|
||||||
|
---@field go_request? boolean -- Log the requests to Gitlab sent by the Go server
|
||||||
|
---@field go_response? boolean -- Log the responses received from Gitlab to the Go server
|
||||||
|
|
||||||
|
---@class PopupSettings: table
|
||||||
|
---@field width? string -- The width of the popup, by default "40%"
|
||||||
|
---@field height? string The width of the popup, by default "60%"
|
||||||
|
---@field border? BorderEnum
|
||||||
|
---@field opacity? number -- From 0.0 (fully transparent) to 1.0 (fully opaque)
|
||||||
|
---@field comment? table -- Individual popup overrides, e.g. { width = "60%", height = "80%", border = "single", opacity = 0.85 },
|
||||||
|
---@field edit? table -- Individual popup overrides, e.g. { width = "60%", height = "80%", border = "single", opacity = 0.85 }
|
||||||
|
---@field note? table -- Individual popup overrides, e.g. { width = "60%", height = "80%", border = "single", opacity = 0.85 }
|
||||||
|
---@field pipeline? table -- Individual popup overrides, e.g. { width = "60%", height = "80%", border = "single", opacity = 0.85 }
|
||||||
|
---@field reply? table -- Individual popup overrides, e.g. { width = "60%", height = "80%", border = "single", opacity = 0.85 }
|
||||||
|
---@field squash_message? string The default message when squashing a commit
|
||||||
|
---@field temp_registers? string[] -- List of registers for backing up popup content (see `:h gitlab.nvim.temp-registers`)
|
||||||
|
|
||||||
|
---@class ChooseMergeRequestSettings
|
||||||
|
---@field open_reviewer? boolean -- Open the reviewer window automatically after switching merge requests
|
||||||
|
|
||||||
|
---@class InfoSettings
|
||||||
|
---@field horizontal? boolean -- Display metadata to the left of the summary rather than underneath
|
||||||
|
---@field fields? ("author" | "created_at" | "updated_at" | "merge_status" | "draft" | "conflicts" | "assignees" | "reviewers" | "pipeline" | "branch" | "target_branch" | "delete_branch" | "squash" | "labels")[]
|
||||||
|
|
||||||
|
---@class DiscussionSettings: table
|
||||||
|
---@field expanders? ExpanderOpts -- Customize the expander icons in the discussion tree
|
||||||
|
---@field auto_open? boolean -- Automatically open when the reviewer is opened
|
||||||
|
---@field default_view? string - Show "discussions" or "notes" by default
|
||||||
|
---@field blacklist? table<string> -- List of usernames to remove from tree (bots, CI, etc)
|
||||||
|
---@field keep_current_open? boolean -- If true, current discussion stays open even if it should otherwise be closed when toggling
|
||||||
|
---@field position? "top" | "right" | "bottom" | "left"
|
||||||
|
---@field size? string -- Size of split, default to "20%"
|
||||||
|
---@field relative? "editor" | "window" -- Relative position of tree split
|
||||||
|
---@field resolved? string -- Symbol to show next to resolved discussions
|
||||||
|
---@field unresolved? '-', -- Symbol to show next to unresolved discussions
|
||||||
|
---@field tree_type? string -- Type of discussion tree - "simple" means just list of discussions, "by_file_name" means file tree with discussions under file
|
||||||
|
---@field draft_mode? boolean -- Whether comments are posted as drafts as part of a review
|
||||||
|
---@field winbar? function -- Custom function to return winbar title, should return a string. Provided with WinbarTable (defined in annotations.lua)
|
||||||
|
|
||||||
|
---@class ExpanderOpts: table<string string>
|
||||||
|
---@field expanded? string -- Icon for expanded discussion thread
|
||||||
|
---@field collapsed? string -- Icon for collapsed discussion thread
|
||||||
|
---@field indentation? string -- Indentation Icon
|
||||||
|
|
||||||
|
---@class Keymaps
|
||||||
|
---@field help? string -- Open a help popup for local keymaps when a relevant view is focused (popup, discussion panel, etc)
|
||||||
|
---@field global? KeymapsGlobal -- Global keybindings which will apply everywhere in Neovim
|
||||||
|
---@field popup? KeymapsPopup -- Keymaps for the popups (creating a comment, reading the summary, etc)
|
||||||
|
---@field discussion_tree? KeymapsDiscussionTree -- Keymaps for the discussion tree pane
|
||||||
|
---@field reviewer? KeymapsReviewer -- Keymaps for the reviewer view
|
||||||
|
|
||||||
|
---@class KeymapTable: table<string, table<string, string | boolean>>
|
||||||
|
---@field disable_all? boolean -- Disable all built-in keymaps
|
||||||
|
|
||||||
|
---@class KeymapsPopup: KeymapTable
|
||||||
|
---@field next_field? string -- Cycle to the next field. Accepts |count|.
|
||||||
|
---@field prev_field? string -- Cycle to the previous field. Accepts |count|.
|
||||||
|
---@field perform_action? string -- Once in normal mode, does action (like saving comment or applying description edit, etc)
|
||||||
|
---@field perform_linewise_action? string -- Once in normal mode, does the linewise action (see logs for this job, etc)
|
||||||
|
---@field discard_changes? string -- Quit the popup discarding changes, the popup content isnot? saved to the `temp_registers` (see `:h gitlab.nvim.temp-registers`)
|
||||||
|
---
|
||||||
|
---@class KeymapsDiscussionTree: KeymapTable
|
||||||
|
---@field add_emoji? string -- Add an emoji to the note/comment
|
||||||
|
---@field delete_emoji? string -- Remove an emoji from a note/comment
|
||||||
|
---@field delete_comment? string -- Delete comment
|
||||||
|
---@field edit_comment? string -- Edit comment
|
||||||
|
---@field reply? string -- Reply to comment
|
||||||
|
---@field toggle_resolved? string -- Toggle the resolved? status of the whole discussion
|
||||||
|
---@field jump_to_file? string -- Jump to comment location in file
|
||||||
|
---@field jump_to_reviewer? string -- Jump to the comment location in the reviewer window
|
||||||
|
---@field open_in_browser? string -- Jump to the URL of the current note/discussion
|
||||||
|
---@field copy_node_url? string -- Copy the URL of the current node to clipboard
|
||||||
|
---@field switch_view? string -- Toggle between the notes and discussions views
|
||||||
|
---@field toggle_tree_type? string or "by_file_name"
|
||||||
|
---@field publish_draft? string -- Publish the currently focused note/comment
|
||||||
|
---@field toggle_draft_mode? string -- Toggle between draft mode (comments posted as drafts) and live mode (comments are posted immediately)
|
||||||
|
---@field toggle_node? string -- Open or close the discussion
|
||||||
|
---@field toggle_all_discussions? string -- Open or close? separately both resolved and unresolved discussions
|
||||||
|
---@field toggle_resolved_discussions? string -- Open or close all resolved discussions
|
||||||
|
---@field toggle_unresolved_discussions? string -- Open or close all unresolved discussions
|
||||||
|
---@field refresh_data? string -- Refresh the data in the view by hitting Gitlab's APIs again
|
||||||
|
---@field print_node? string -- Print the current node (for debugging)
|
||||||
|
---
|
||||||
|
---@class KeymapsReviewer: KeymapTable
|
||||||
|
---@field create_comment? string -- Create a comment for the lines that the following {motion} moves over. Repeat the key(s) for creating comment for the current line
|
||||||
|
---@field create_suggestion? string -- Creates suggestion for the lines that the following {motion} moves over. Repeat the key(s) for creating comment for the current line
|
||||||
|
---@field move_to_discussion_tree? string -- Jump to the comment in the discussion tree
|
||||||
|
---
|
||||||
|
---@class KeymapsGlobal: KeymapTable
|
||||||
|
---@field add_assignee? string -- Add an assignee to the merge request
|
||||||
|
---@field delete_assignee? string -- Delete an assignee from the merge request
|
||||||
|
---@field add_label? string -- Add a label from the merge request
|
||||||
|
---@field delete_label? string -- Remove a label from the merge request
|
||||||
|
---@field add_reviewer? string -- Add a reviewer to the merge request
|
||||||
|
---@field delete_reviewer? string -- Delete a reviewer from the merge request
|
||||||
|
---@field approve? string -- Approve MR
|
||||||
|
---@field revoke? string -- Revoke MR approval
|
||||||
|
---@field merge? string -- Merge the feature branch to the target branch and close MR
|
||||||
|
---@field create_mr? string -- Create a new MR for currently checked-out feature branch
|
||||||
|
---@field choose_merge_request? string -- Chose MR for review (if necessary check out the feature branch)
|
||||||
|
---@field start_review? string -- Start review for the currently checked-out branch
|
||||||
|
---@field summary? string -- Show the editable summary of the MR
|
||||||
|
---@field copy_mr_url? string -- Copy the URL of the MR to the system clipboard
|
||||||
|
---@field open_in_browser? string -- Openthe URL of the MR in the default Internet browser
|
||||||
|
---@field create_note? string -- Create a note (comment not linked toa specific line)
|
||||||
|
---@field pipeline? string -- Show the pipeline status
|
||||||
|
---@field toggle_discussions? string -- Toggle the discussions window
|
||||||
|
---@field toggle_draft_mode? string -- Toggle between draft mode (comments posted as drafts) and live mode (comments are posted immediately)
|
||||||
|
---@field publish_all_drafts? string -- Publish all draft comments/notes
|
||||||
|
|
||||||
|
---@class Settings: KeymapTable
|
||||||
|
---@field next_field? string -- Cycle to the next field. Accepts |count|.
|
||||||
|
---@field prev_field? string -- Cycle to the previous field. Accepts |count|.
|
||||||
|
---@field perform_action? string -- Once in normal mode, does action (like saving comment or applying description edit, etc)
|
||||||
|
---@field perform_linewise_action? string -- Once in normal mode, does the linewise action (see logs for this job, etc)
|
||||||
|
---@field discard_changes? string -- Quit the popup discarding changes, the popup content is not? saved to the `temp_registers` (see `:h gitlab.nvim.temp-registers`)
|
||||||
@@ -36,7 +36,7 @@ function async:fetch(dependencies, i, argTable)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Call the API, set the data, and then call the next API
|
-- Call the API, set the data, and then call the next API
|
||||||
local body = dependency.body and dependency.body() or nil
|
local body = dependency.body and dependency.body(argTable) or nil
|
||||||
job.run_job(dependency.endpoint, dependency.method or "GET", body, function(data)
|
job.run_job(dependency.endpoint, dependency.method or "GET", body, function(data)
|
||||||
state[dependency.state] = dependency.key and data[dependency.key] or data
|
state[dependency.state] = dependency.key and data[dependency.key] or data
|
||||||
self:fetch(dependencies, i + 1, argTable)
|
self:fetch(dependencies, i + 1, argTable)
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ end
|
|||||||
---Return the list of names of all remote-tracking branches or an empty list.
|
---Return the list of names of all remote-tracking branches or an empty list.
|
||||||
---@return table, string|nil
|
---@return table, string|nil
|
||||||
M.get_all_remote_branches = function()
|
M.get_all_remote_branches = function()
|
||||||
|
local state = require("gitlab.state")
|
||||||
local all_branches, err = M.branches({ "--remotes" })
|
local all_branches, err = M.branches({ "--remotes" })
|
||||||
if err ~= nil then
|
if err ~= nil then
|
||||||
return {}, err
|
return {}, err
|
||||||
@@ -76,8 +77,8 @@ M.get_all_remote_branches = function()
|
|||||||
local lines = u.lines_into_table(all_branches)
|
local lines = u.lines_into_table(all_branches)
|
||||||
return List.new(lines)
|
return List.new(lines)
|
||||||
:map(function(line)
|
:map(function(line)
|
||||||
-- Trim "origin/"
|
-- Trim the remote branch
|
||||||
return line:match("origin/(%S+)")
|
return line:match(state.settings.connection_settings.remote .. "/(%S+)")
|
||||||
end)
|
end)
|
||||||
:filter(function(branch)
|
:filter(function(branch)
|
||||||
-- Don't include the HEAD pointer
|
-- Don't include the HEAD pointer
|
||||||
@@ -96,6 +97,7 @@ end
|
|||||||
---@param log_level integer
|
---@param log_level integer
|
||||||
---@return boolean|nil
|
---@return boolean|nil
|
||||||
M.current_branch_up_to_date_on_remote = function(log_level)
|
M.current_branch_up_to_date_on_remote = function(log_level)
|
||||||
|
local state = require("gitlab.state")
|
||||||
local current_branch = M.get_current_branch()
|
local current_branch = M.get_current_branch()
|
||||||
local handle = io.popen("git branch -r --contains " .. current_branch .. " 2>&1")
|
local handle = io.popen("git branch -r --contains " .. current_branch .. " 2>&1")
|
||||||
if not handle then
|
if not handle then
|
||||||
@@ -110,13 +112,16 @@ M.current_branch_up_to_date_on_remote = function(log_level)
|
|||||||
handle:close()
|
handle:close()
|
||||||
|
|
||||||
local current_head_on_remote = List.new(remote_branches_with_current_head):filter(function(line)
|
local current_head_on_remote = List.new(remote_branches_with_current_head):filter(function(line)
|
||||||
return line == " origin/" .. current_branch
|
return line == string.format(" %s/", state.settings.connection_settings.remote) .. current_branch
|
||||||
end)
|
end)
|
||||||
local remote_up_to_date = #current_head_on_remote == 1
|
local remote_up_to_date = #current_head_on_remote == 1
|
||||||
|
|
||||||
if not remote_up_to_date then
|
if not remote_up_to_date then
|
||||||
require("gitlab.utils").notify(
|
require("gitlab.utils").notify(
|
||||||
"You have local commits that are not on origin. Have you forgotten to push?",
|
string.format(
|
||||||
|
"You have local commits that are not on %s. Have you forgotten to push?",
|
||||||
|
state.settings.connection_settings.remote
|
||||||
|
),
|
||||||
log_level
|
log_level
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
146
lua/gitlab/health.lua
Normal file
146
lua/gitlab/health.lua
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
local state = require("gitlab.state")
|
||||||
|
local List = require("gitlab.utils.list")
|
||||||
|
local u = require("gitlab.utils")
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
local function check_go_version()
|
||||||
|
local go_version = io.popen("go version"):read("*a")
|
||||||
|
if go_version then
|
||||||
|
local major, minor, _ = go_version:match("(%d+)%.(%d+)%.(%d+)")
|
||||||
|
if major and tonumber(major) >= 1 and tonumber(minor) >= 19 then
|
||||||
|
return
|
||||||
|
else
|
||||||
|
return "Go is installed, but version is older than 1.19."
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return "Go is not installed."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---Checks the health of the plugin
|
||||||
|
---@param return_results boolean
|
||||||
|
M.check = function(return_results)
|
||||||
|
local warnings = List.new({})
|
||||||
|
local errors = List.new({})
|
||||||
|
|
||||||
|
if not return_results then
|
||||||
|
vim.health.start("gitlab.nvim")
|
||||||
|
end
|
||||||
|
|
||||||
|
if state.settings.reviewer == "delta" then
|
||||||
|
table.insert(
|
||||||
|
warnings,
|
||||||
|
"Delta is no longer a supported reviewer, please use diffview and update your setup function"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local required_deps = {
|
||||||
|
{
|
||||||
|
name = "MunifTanjim/nui.nvim",
|
||||||
|
package = "nui.popup",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "nvim-lua/plenary.nvim",
|
||||||
|
package = "plenary",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "sindrets/diffview.nvim",
|
||||||
|
package = "diffview",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local recommended_deps = {
|
||||||
|
{
|
||||||
|
name = "stevearc/dressing.nvim",
|
||||||
|
package = "dressing",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "nvim-tree/nvim-web-devicons",
|
||||||
|
package = "nvim-web-devicons",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local go_version_problem = check_go_version()
|
||||||
|
if go_version_problem ~= nil then
|
||||||
|
table.insert(warnings, go_version_problem)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, dep in ipairs(required_deps) do
|
||||||
|
local ok, _ = pcall(require, dep.package)
|
||||||
|
if not ok then
|
||||||
|
table.insert(errors, string.format("%s is a required dependency, but cannot be found", dep.name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, dep in ipairs(recommended_deps) do
|
||||||
|
local ok, _ = pcall(require, dep.package)
|
||||||
|
if not ok then
|
||||||
|
table.insert(warnings, string.format("%s is a recommended dependency", dep.name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local removed_fields_in_user_config = {}
|
||||||
|
local removed_settings_fields = {
|
||||||
|
"dialogue",
|
||||||
|
"discussion_tree.add_emoji",
|
||||||
|
"discussion_tree.copy_node_url",
|
||||||
|
"discussion_tree.delete_comment",
|
||||||
|
"discussion_tree.delete_emoji",
|
||||||
|
"discussion_tree.edit_comment",
|
||||||
|
"discussion_tree.jump_to_file",
|
||||||
|
"discussion_tree.jump_to_reviewer",
|
||||||
|
"discussion_tree.open_in_browser",
|
||||||
|
"discussion_tree.publish_draft",
|
||||||
|
"discussion_tree.refresh_data",
|
||||||
|
"discussion_tree.reply",
|
||||||
|
"discussion_tree.switch_view",
|
||||||
|
"discussion_tree.toggle_all_discussions",
|
||||||
|
"discussion_tree.toggle_draft_mode",
|
||||||
|
"discussion_tree.toggle_node",
|
||||||
|
"discussion_tree.toggle_resolved",
|
||||||
|
"discussion_tree.toggle_resolved_discussions",
|
||||||
|
"discussion_tree.toggle_tree_type",
|
||||||
|
"discussion_tree.toggle_unresolved_discussions",
|
||||||
|
"help",
|
||||||
|
"popup.keymaps.next_field",
|
||||||
|
"popup.keymaps.prev_field",
|
||||||
|
"popup.perform_action",
|
||||||
|
"popup.perform_linewise_action",
|
||||||
|
"review_pane", -- Only relevant for the Delta reviewer
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field in ipairs(removed_settings_fields) do
|
||||||
|
if u.get_nested_field(state.settings, field) ~= nil then
|
||||||
|
table.insert(removed_fields_in_user_config, field)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #removed_fields_in_user_config ~= 0 then
|
||||||
|
table.insert(
|
||||||
|
warnings,
|
||||||
|
"The following settings fields have been removed:\n" .. table.concat(removed_fields_in_user_config, "\n")
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if #errors > 0 then
|
||||||
|
for _, err in ipairs(errors) do
|
||||||
|
vim.health.error(err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #warnings > 0 then
|
||||||
|
for _, err in ipairs(warnings) do
|
||||||
|
vim.health.warn(err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #warnings + #errors == 0 then
|
||||||
|
vim.health.ok("Gitlab plugin is okay!")
|
||||||
|
end
|
||||||
|
|
||||||
|
if return_results then
|
||||||
|
return #warnings + #errors == 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
@@ -17,6 +17,7 @@ local create_mr = require("gitlab.actions.create_mr")
|
|||||||
local approvals = require("gitlab.actions.approvals")
|
local approvals = require("gitlab.actions.approvals")
|
||||||
local draft_notes = require("gitlab.actions.draft_notes")
|
local draft_notes = require("gitlab.actions.draft_notes")
|
||||||
local labels = require("gitlab.actions.labels")
|
local labels = require("gitlab.actions.labels")
|
||||||
|
local health = require("gitlab.health")
|
||||||
|
|
||||||
local user = state.dependencies.user
|
local user = state.dependencies.user
|
||||||
local info = state.dependencies.info
|
local info = state.dependencies.info
|
||||||
@@ -28,8 +29,9 @@ local merge_requests_dep = state.dependencies.merge_requests
|
|||||||
local draft_notes_dep = state.dependencies.draft_notes
|
local draft_notes_dep = state.dependencies.draft_notes
|
||||||
local discussion_data = state.dependencies.discussion_data
|
local discussion_data = state.dependencies.discussion_data
|
||||||
|
|
||||||
return {
|
---@param args Settings | {} | nil
|
||||||
setup = function(args)
|
---@return nil
|
||||||
|
local function setup(args)
|
||||||
if args == nil then
|
if args == nil then
|
||||||
args = {}
|
args = {}
|
||||||
end
|
end
|
||||||
@@ -40,8 +42,15 @@ return {
|
|||||||
reviewer.init()
|
reviewer.init()
|
||||||
discussions.initialize_discussions() -- place signs / diagnostics for discussions in reviewer
|
discussions.initialize_discussions() -- place signs / diagnostics for discussions in reviewer
|
||||||
emoji.init() -- Read in emojis for lookup purposes
|
emoji.init() -- Read in emojis for lookup purposes
|
||||||
end,
|
|
||||||
-- Global Actions 🌎
|
local is_healthy = health.check(true)
|
||||||
|
if not is_healthy then
|
||||||
|
u.notify("Plugin unhealthy, please run ':checkhealth gitlab' for details", vim.log.levels.WARN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
setup = setup,
|
||||||
summary = async.sequence({
|
summary = async.sequence({
|
||||||
u.merge(info, { refresh = true }),
|
u.merge(info, { refresh = true }),
|
||||||
labels_dep,
|
labels_dep,
|
||||||
|
|||||||
@@ -9,20 +9,21 @@ local M = {}
|
|||||||
|
|
||||||
-- Starts the Go server and call the callback provided
|
-- Starts the Go server and call the callback provided
|
||||||
M.start = function(callback)
|
M.start = function(callback)
|
||||||
local empty_port = "''"
|
local port = tonumber(state.settings.port) or 0
|
||||||
local port = state.settings.port or empty_port
|
|
||||||
local parsed_port = nil
|
local parsed_port = nil
|
||||||
local callback_called = false
|
local callback_called = false
|
||||||
local command = string.format(
|
|
||||||
"%s %s %s %s '%s' %s '%s'",
|
local go_server_settings = {
|
||||||
state.settings.bin,
|
gitlab_url = state.settings.gitlab_url,
|
||||||
state.settings.gitlab_url,
|
port = port,
|
||||||
port,
|
auth_token = state.settings.auth_token,
|
||||||
state.settings.auth_token,
|
debug = state.settings.debug,
|
||||||
vim.json.encode(state.settings.debug),
|
log_path = state.settings.log_path,
|
||||||
state.settings.log_path,
|
connection_settings = state.settings.connection_settings,
|
||||||
vim.json.encode(state.settings.connection_settings)
|
}
|
||||||
)
|
|
||||||
|
local settings = vim.json.encode(go_server_settings)
|
||||||
|
local command = string.format("%s '%s'", state.settings.bin, settings)
|
||||||
|
|
||||||
local job_id = vim.fn.jobstart(command, {
|
local job_id = vim.fn.jobstart(command, {
|
||||||
on_stdout = function(_, data)
|
on_stdout = function(_, data)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ M.default_auth_provider = function()
|
|||||||
return auth_token, gitlab_url, err
|
return auth_token, gitlab_url, err
|
||||||
end
|
end
|
||||||
|
|
||||||
-- These are the default settings for the plugin
|
--- These are the default settings for the plugin
|
||||||
M.settings = {
|
M.settings = {
|
||||||
auth_provider = M.default_auth_provider,
|
auth_provider = M.default_auth_provider,
|
||||||
port = nil, -- choose random port
|
port = nil, -- choose random port
|
||||||
@@ -57,7 +57,8 @@ M.settings = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
connection_settings = {
|
connection_settings = {
|
||||||
insecure = true,
|
insecure = false,
|
||||||
|
remote = "origin",
|
||||||
},
|
},
|
||||||
attachment_dir = "",
|
attachment_dir = "",
|
||||||
keymaps = {
|
keymaps = {
|
||||||
@@ -375,72 +376,12 @@ M.set_global_keymaps = function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Merges user settings into the default settings, overriding them
|
-- Merges user settings into the default settings, overriding them
|
||||||
|
---@param args Settings
|
||||||
|
---@return Settings
|
||||||
M.merge_settings = function(args)
|
M.merge_settings = function(args)
|
||||||
M.settings = u.merge(M.settings, args)
|
M.settings = u.merge(M.settings, args)
|
||||||
|
|
||||||
-- Check deprecated settings and alert users!
|
|
||||||
if M.settings.dialogue ~= nil then
|
|
||||||
u.notify("The dialogue field has been deprecated, please remove it from your setup function", vim.log.levels.WARN)
|
|
||||||
end
|
|
||||||
|
|
||||||
if M.settings.reviewer == "delta" then
|
|
||||||
u.notify(
|
|
||||||
"Delta is no longer a supported reviewer, please use diffview and update your setup function",
|
|
||||||
vim.log.levels.ERROR
|
|
||||||
)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local diffview_ok, _ = pcall(require, "diffview")
|
|
||||||
if not diffview_ok then
|
|
||||||
u.notify("Please install diffview, it is required")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local removed_fields_in_user_config = {}
|
|
||||||
local removed_settings_fields = {
|
|
||||||
"discussion_tree.add_emoji",
|
|
||||||
"discussion_tree.copy_node_url",
|
|
||||||
"discussion_tree.delete_comment",
|
|
||||||
"discussion_tree.delete_emoji",
|
|
||||||
"discussion_tree.edit_comment",
|
|
||||||
"discussion_tree.jump_to_file",
|
|
||||||
"discussion_tree.jump_to_reviewer",
|
|
||||||
"discussion_tree.open_in_browser",
|
|
||||||
"discussion_tree.publish_draft",
|
|
||||||
"discussion_tree.refresh_data",
|
|
||||||
"discussion_tree.reply",
|
|
||||||
"discussion_tree.switch_view",
|
|
||||||
"discussion_tree.toggle_all_discussions",
|
|
||||||
"discussion_tree.toggle_draft_mode",
|
|
||||||
"discussion_tree.toggle_node",
|
|
||||||
"discussion_tree.toggle_resolved",
|
|
||||||
"discussion_tree.toggle_resolved_discussions",
|
|
||||||
"discussion_tree.toggle_tree_type",
|
|
||||||
"discussion_tree.toggle_unresolved_discussions",
|
|
||||||
"help",
|
|
||||||
"popup.keymaps.next_field",
|
|
||||||
"popup.keymaps.prev_field",
|
|
||||||
"popup.perform_action",
|
|
||||||
"popup.perform_linewise_action",
|
|
||||||
"review_pane", -- Only relevant for the Delta reviewer
|
|
||||||
}
|
|
||||||
for _, field in ipairs(removed_settings_fields) do
|
|
||||||
if u.get_nested_field(M.settings, field) ~= nil then
|
|
||||||
table.insert(removed_fields_in_user_config, field)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if #removed_fields_in_user_config ~= 0 then
|
|
||||||
u.notify(
|
|
||||||
"The following settings fields have been removed:\n" .. table.concat(removed_fields_in_user_config, "\n"),
|
|
||||||
vim.log.levels.WARN
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
M.settings.file_separator = (u.is_windows() and "\\" or "/")
|
M.settings.file_separator = (u.is_windows() and "\\" or "/")
|
||||||
|
return M.settings
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
M.print_settings = function()
|
M.print_settings = function()
|
||||||
@@ -616,7 +557,18 @@ M.dependencies = {
|
|||||||
endpoint = "/merge_requests",
|
endpoint = "/merge_requests",
|
||||||
key = "merge_requests",
|
key = "merge_requests",
|
||||||
state = "MERGE_REQUESTS",
|
state = "MERGE_REQUESTS",
|
||||||
refresh = false,
|
refresh = true,
|
||||||
|
method = "POST",
|
||||||
|
body = function(opts)
|
||||||
|
local listArgs = {
|
||||||
|
label = opts and opts.label or {},
|
||||||
|
notlabel = opts and opts.notlabel or {},
|
||||||
|
}
|
||||||
|
for k, v in pairs(listArgs) do
|
||||||
|
listArgs[k] = v
|
||||||
|
end
|
||||||
|
return listArgs
|
||||||
|
end,
|
||||||
},
|
},
|
||||||
discussion_data = {
|
discussion_data = {
|
||||||
-- key is missing here...
|
-- key is missing here...
|
||||||
|
|||||||
Reference in New Issue
Block a user