Files
aiops/backend/internal/api/handlers/pipeline.go
T

307 lines
7.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"net/http"
"strconv"
"ezops/internal/models"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// PipelineHandler 流水线处理器(流水线 + 应用发布两个子域,应用发布方法拆分至 pipeline_release.go) // Logan.Li
type PipelineHandler struct {
db *gorm.DB
}
// NewPipelineHandler 创建流水线处理器
func NewPipelineHandler(db *gorm.DB) *PipelineHandler {
return &PipelineHandler{db: db}
}
// ListPipelines 获取流水线列表
// @Summary 获取流水线列表
// @Description 获取所有流水线列表
// @Tags 流水线
// @Produce json
// @Security Bearer
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} models.Response{data=models.ListResponse}
// @Router /pipelines [get]
func (h *PipelineHandler) ListPipelines(c *gin.Context) {
var query models.PageQuery
c.ShouldBindQuery(&query)
var total int64
h.db.Model(&models.Pipeline{}).Count(&total)
var pipelines []models.Pipeline
h.db.Offset(query.GetOffset()).Limit(query.GetLimit()).Find(&pipelines)
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
Data: models.ListResponse{
List: pipelines,
Total: total,
},
})
}
// GetPipeline 获取流水线详情
// @Summary 获取流水线详情
// @Description 获取指定流水线的详细信息
// @Tags 流水线
// @Produce json
// @Security Bearer
// @Param id path int true "流水线ID"
// @Success 200 {object} models.Response{data=models.Pipeline}
// @Router /pipelines/{id} [get]
func (h *PipelineHandler) GetPipeline(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var pipeline models.Pipeline
if err := h.db.First(&pipeline, id).Error; err != nil {
c.JSON(http.StatusNotFound, models.Response{
Code: 404,
Message: "流水线不存在",
})
return
}
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
Data: pipeline,
})
}
// CreatePipeline 创建流水线
// @Summary 创建流水线
// @Description 创建新流水线
// @Tags 流水线
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body models.CreatePipelineRequest true "创建请求"
// @Success 200 {object} models.Response{data=models.Pipeline}
// @Router /pipelines [post]
func (h *PipelineHandler) CreatePipeline(c *gin.Context) {
var req models.CreatePipelineRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.Response{
Code: 400,
Message: "请求参数错误: " + err.Error(),
})
return
}
pipeline := models.Pipeline{
Name: req.Name,
Code: req.Code,
Description: req.Description,
Type: req.Type,
Source: req.Source,
Branch: req.Branch,
Dockerfile: req.Dockerfile,
Stages: req.Stages,
Variables: req.Variables,
Enabled: true,
}
if err := h.db.Create(&pipeline).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{
Code: 500,
Message: "创建失败",
})
return
}
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "创建成功",
Data: pipeline,
})
}
// UpdatePipeline 更新流水线
// @Summary 更新流水线
// @Description 更新指定流水线
// @Tags 流水线
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "流水线ID"
// @Param request body models.CreatePipelineRequest true "更新请求"
// @Success 200 {object} models.Response{data=models.Pipeline}
// @Router /pipelines/{id} [put]
func (h *PipelineHandler) UpdatePipeline(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var req models.CreatePipelineRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.Response{
Code: 400,
Message: "请求参数错误: " + err.Error(),
})
return
}
var pipeline models.Pipeline
if err := h.db.First(&pipeline, id).Error; err != nil {
c.JSON(http.StatusNotFound, models.Response{
Code: 404,
Message: "流水线不存在",
})
return
}
updates := map[string]interface{}{
"name": req.Name,
"description": req.Description,
"type": req.Type,
"source": req.Source,
"branch": req.Branch,
"dockerfile": req.Dockerfile,
"stages": req.Stages,
"variables": req.Variables,
}
if err := h.db.Model(&pipeline).Updates(updates).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{
Code: 500,
Message: "更新失败",
})
return
}
h.db.First(&pipeline, id)
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "更新成功",
Data: pipeline,
})
}
// DeletePipeline 删除流水线
// @Summary 删除流水线
// @Description 删除指定流水线
// @Tags 流水线
// @Produce json
// @Security Bearer
// @Param id path int true "流水线ID"
// @Success 200 {object} models.Response
// @Router /pipelines/{id} [delete]
func (h *PipelineHandler) DeletePipeline(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
if err := h.db.Delete(&models.Pipeline{}, id).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{
Code: 500,
Message: "删除失败",
})
return
}
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "删除成功",
})
}
// TriggerPipeline 触发流水线
// @Summary 触发流水线
// @Description 手动触发流水线执行
// @Tags 流水线
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "流水线ID"
// @Param request body models.TriggerPipelineRequest true "触发请求"
// @Success 200 {object} models.Response{data=models.PipelineRun}
// @Router /pipelines/{id}/trigger [post]
func (h *PipelineHandler) TriggerPipeline(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var pipeline models.Pipeline
if err := h.db.First(&pipeline, id).Error; err != nil {
c.JSON(http.StatusNotFound, models.Response{
Code: 404,
Message: "流水线不存在",
})
return
}
var req models.TriggerPipelineRequest
c.ShouldBindJSON(&req)
// 获取最新构建号
var maxBuildNumber int
h.db.Model(&models.PipelineRun{}).Where("pipeline_id = ?", id).Select("COALESCE(MAX(build_number), 0)").Scan(&maxBuildNumber)
run := models.PipelineRun{
PipelineID: uint(id),
BuildNumber: maxBuildNumber + 1,
Status: "pending",
Branch: req.Branch,
TriggeredBy: "manual",
}
if req.Branch == "" {
run.Branch = pipeline.Branch
}
if err := h.db.Create(&run).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{
Code: 500,
Message: "触发失败",
})
return
}
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "触发成功",
Data: run,
})
}
// ListRuns 获取运行记录列表
// @Summary 获取运行记录列表
// @Description 获取指定流水线的运行记录
// @Tags 流水线
// @Produce json
// @Security Bearer
// @Param id path int true "流水线ID"
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} models.Response{data=models.ListResponse}
// @Router /pipelines/{id}/runs [get]
func (h *PipelineHandler) ListRuns(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var query models.PageQuery
c.ShouldBindQuery(&query)
db := h.db.Model(&models.PipelineRun{}).Where("pipeline_id = ?", id)
var total int64
db.Count(&total)
var runs []models.PipelineRun
db.Order("created_at DESC").
Offset(query.GetOffset()).
Limit(query.GetLimit()).
Find(&runs)
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
Data: models.ListResponse{
List: runs,
Total: total,
},
})
}