89 lines
3.1 KiB
Go
89 lines
3.1 KiB
Go
package gitlab
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// RegisterTaskMRHTTPRoutes registers the explicit link/unlink endpoints on an
|
|
// existing /api/v1/gitlab router group.
|
|
func (c *Controller) RegisterTaskMRHTTPRoutes(api *gin.RouterGroup) {
|
|
api.POST("/task-mrs", c.httpCreateTaskMR)
|
|
api.DELETE("/task-mrs/:associationID", c.httpDeleteTaskMR)
|
|
}
|
|
|
|
type createTaskMRRequest struct {
|
|
TaskID string `json:"task_id"`
|
|
RepositoryID string `json:"repository_id"`
|
|
MRURL string `json:"mr_url"`
|
|
}
|
|
|
|
func (c *Controller) httpCreateTaskMR(ctx *gin.Context) {
|
|
workspaceID := c.workspaceID(ctx)
|
|
if workspaceID == "" {
|
|
ctx.JSON(http.StatusBadRequest, gin.H{responseErrorKey: "workspace_id query parameter required"})
|
|
return
|
|
}
|
|
var request createTaskMRRequest
|
|
if err := ctx.ShouldBindJSON(&request); err != nil || strings.TrimSpace(request.TaskID) == "" || strings.TrimSpace(request.MRURL) == "" {
|
|
ctx.JSON(http.StatusBadRequest, gin.H{responseErrorKey: "task_id and mr_url are required"})
|
|
return
|
|
}
|
|
association, err := c.service.AssociateExistingMRByURL(
|
|
ctx.Request.Context(), workspaceID, request.TaskID, request.RepositoryID, request.MRURL,
|
|
)
|
|
if err != nil {
|
|
c.logger.Error("link task merge request failed",
|
|
zap.String("task_id", request.TaskID), zap.Error(err))
|
|
writeTaskMRError(ctx, err)
|
|
return
|
|
}
|
|
ctx.JSON(http.StatusOK, association)
|
|
}
|
|
|
|
func (c *Controller) httpDeleteTaskMR(ctx *gin.Context) {
|
|
workspaceID := c.workspaceID(ctx)
|
|
associationID := strings.TrimSpace(ctx.Param("associationID"))
|
|
if workspaceID == "" || associationID == "" {
|
|
ctx.JSON(http.StatusBadRequest, gin.H{responseErrorKey: "workspace_id and association_id are required"})
|
|
return
|
|
}
|
|
if err := c.service.UnlinkTaskMR(ctx.Request.Context(), workspaceID, associationID); err != nil {
|
|
c.logger.Error("unlink task merge request failed",
|
|
zap.String("association_id", associationID), zap.Error(err))
|
|
writeTaskMRError(ctx, err)
|
|
return
|
|
}
|
|
ctx.JSON(http.StatusOK, gin.H{"deleted": true})
|
|
}
|
|
|
|
func writeTaskMRError(ctx *gin.Context, err error) {
|
|
status := http.StatusInternalServerError
|
|
message := "GitLab task merge request operation failed"
|
|
switch {
|
|
case errors.Is(err, ErrWorkspaceRequired):
|
|
status = http.StatusBadRequest
|
|
message = "workspace_id query parameter required"
|
|
case errors.Is(err, ErrInvalidMRURL):
|
|
status = http.StatusBadRequest
|
|
message = "invalid GitLab merge request URL"
|
|
case errors.Is(err, ErrTaskMRNotFound):
|
|
status = http.StatusNotFound
|
|
message = "task merge request association not found"
|
|
case errors.Is(err, ErrTaskMRRepositoryRequired):
|
|
status = http.StatusConflict
|
|
message = "repository_id is required for multi-repository tasks"
|
|
case errors.Is(err, ErrTaskMRRepositoryMismatch):
|
|
status = http.StatusUnprocessableEntity
|
|
message = "repository does not match GitLab merge request"
|
|
case errors.Is(err, ErrNotConfigured), errors.Is(err, ErrNoClient):
|
|
status = http.StatusServiceUnavailable
|
|
message = providerActionFailedMessage + ": connection resolution"
|
|
}
|
|
ctx.JSON(status, gin.H{responseErrorKey: message})
|
|
}
|