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, }, }) }