Adds support for notes. These are comments that are not linked to specific lines of code in the MR.
203 lines
5.3 KiB
Go
203 lines
5.3 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/xanzy/go-gitlab"
|
|
)
|
|
|
|
const mrVersionsUrl = "%s/api/v4/projects/%s/merge_requests/%d/versions"
|
|
|
|
type PostCommentRequest struct {
|
|
Comment string `json:"comment"`
|
|
FileName string `json:"file_name"`
|
|
NewLine int `json:"new_line"`
|
|
OldLine int `json:"old_line"`
|
|
HeadCommitSHA string `json:"head_commit_sha"`
|
|
BaseCommitSHA string `json:"base_commit_sha"`
|
|
StartCommitSHA string `json:"start_commit_sha"`
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
type DeleteCommentRequest struct {
|
|
NoteId int `json:"note_id"`
|
|
DiscussionId string `json:"discussion_id"`
|
|
}
|
|
|
|
type EditCommentRequest struct {
|
|
Comment string `json:"comment"`
|
|
NoteId int `json:"note_id"`
|
|
DiscussionId string `json:"discussion_id"`
|
|
Resolved bool `json:"resolved"`
|
|
}
|
|
|
|
type CommentResponse struct {
|
|
SuccessResponse
|
|
Comment *gitlab.Note `json:"note"`
|
|
Discussion *gitlab.Discussion `json:"discussion"`
|
|
}
|
|
|
|
func CommentHandler(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case http.MethodDelete:
|
|
DeleteComment(w, r)
|
|
case http.MethodPost:
|
|
PostComment(w, r)
|
|
case http.MethodPatch:
|
|
EditComment(w, r)
|
|
default:
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
}
|
|
}
|
|
|
|
func DeleteComment(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
c := r.Context().Value("client").(Client)
|
|
|
|
body, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
c.handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
var deleteCommentRequest DeleteCommentRequest
|
|
err = json.Unmarshal(body, &deleteCommentRequest)
|
|
if err != nil {
|
|
c.handleError(w, err, "Could not read JSON from request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
res, err := c.git.Discussions.DeleteMergeRequestDiscussionNote(c.projectId, c.mergeId, deleteCommentRequest.DiscussionId, deleteCommentRequest.NoteId)
|
|
|
|
if err != nil {
|
|
c.handleError(w, err, "Could not delete comment", res.StatusCode)
|
|
return
|
|
}
|
|
|
|
/* TODO: Check status code */
|
|
w.WriteHeader(http.StatusOK)
|
|
response := SuccessResponse{
|
|
Message: "Comment deleted succesfully",
|
|
Status: http.StatusOK,
|
|
}
|
|
|
|
json.NewEncoder(w).Encode(response)
|
|
}
|
|
|
|
func PostComment(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
c := r.Context().Value("client").(Client)
|
|
|
|
body, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
c.handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
var postCommentRequest PostCommentRequest
|
|
err = json.Unmarshal(body, &postCommentRequest)
|
|
if err != nil {
|
|
c.handleError(w, err, "Could not unmarshal data from request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
opt := gitlab.CreateMergeRequestDiscussionOptions{
|
|
Body: &postCommentRequest.Comment,
|
|
}
|
|
|
|
/* If we are leaving a comment on a line, leave position. Otherwise,
|
|
we are leaving a note (unlinked comment) */
|
|
if postCommentRequest.FileName != "" {
|
|
opt.Position = &gitlab.NotePosition{
|
|
PositionType: "text",
|
|
StartSHA: postCommentRequest.StartCommitSHA,
|
|
HeadSHA: postCommentRequest.HeadCommitSHA,
|
|
BaseSHA: postCommentRequest.BaseCommitSHA,
|
|
NewPath: postCommentRequest.FileName,
|
|
OldPath: postCommentRequest.FileName,
|
|
NewLine: postCommentRequest.NewLine,
|
|
OldLine: postCommentRequest.OldLine,
|
|
}
|
|
}
|
|
|
|
discussion, _, err := c.git.Discussions.CreateMergeRequestDiscussion(c.projectId, c.mergeId, &opt)
|
|
|
|
if err != nil {
|
|
c.handleError(w, err, "Could not create comment", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
response := CommentResponse{
|
|
SuccessResponse: SuccessResponse{
|
|
Message: "Comment updated succesfully",
|
|
Status: http.StatusOK,
|
|
},
|
|
Comment: discussion.Notes[0],
|
|
Discussion: discussion,
|
|
}
|
|
|
|
json.NewEncoder(w).Encode(response)
|
|
}
|
|
|
|
func EditComment(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
c := r.Context().Value("client").(Client)
|
|
|
|
body, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
c.handleError(w, err, "Could not read request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
var editCommentRequest EditCommentRequest
|
|
err = json.Unmarshal(body, &editCommentRequest)
|
|
if err != nil {
|
|
c.handleError(w, err, "Could not unmarshal data from request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
options := gitlab.UpdateMergeRequestDiscussionNoteOptions{}
|
|
|
|
/* The PATCH can either be to the resolved status of
|
|
the discussion or or the text of the comment */
|
|
msg := "edit comment"
|
|
if editCommentRequest.Comment == "" {
|
|
options.Resolved = &editCommentRequest.Resolved
|
|
msg = "update discussion status"
|
|
} else {
|
|
options.Body = gitlab.String(editCommentRequest.Comment)
|
|
}
|
|
|
|
note, res, err := c.git.Discussions.UpdateMergeRequestDiscussionNote(c.projectId, c.mergeId, editCommentRequest.DiscussionId, editCommentRequest.NoteId, &options)
|
|
|
|
if err != nil {
|
|
c.handleError(w, err, "Could not "+msg, res.StatusCode)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(res.StatusCode)
|
|
|
|
if res.StatusCode != http.StatusOK {
|
|
c.handleError(w, errors.New("Non-200 status code recieved"), "Could not "+msg, res.StatusCode)
|
|
}
|
|
|
|
response := CommentResponse{
|
|
SuccessResponse: SuccessResponse{
|
|
Message: "Comment updated succesfully",
|
|
Status: http.StatusOK,
|
|
},
|
|
Comment: note,
|
|
}
|
|
|
|
json.NewEncoder(w).Encode(response)
|
|
}
|