diff --git a/cmd/server/openapi/docs.go b/cmd/server/openapi/docs.go index 59e148fc4..8b7c33c60 100644 --- a/cmd/server/openapi/docs.go +++ b/cmd/server/openapi/docs.go @@ -2984,6 +2984,12 @@ const docTemplate = `{ "description": "filter pipelines by strings contained in ref", "name": "ref", "in": "query" + }, + { + "type": "string", + "description": "filter pipelines by status", + "name": "status", + "in": "query" } ], "responses": { diff --git a/server/api/pipeline.go b/server/api/pipeline.go index fa9d4ce6c..400eaf357 100644 --- a/server/api/pipeline.go +++ b/server/api/pipeline.go @@ -120,6 +120,7 @@ func createTmpPipeline(event model.WebhookEvent, commit *model.Commit, user *mod // @Param branch query string false "filter pipelines by branch" // @Param event query string false "filter pipelines by webhook events (comma separated)" // @Param ref query string false "filter pipelines by strings contained in ref" +// @Param status query string false "filter pipelines by status" func GetPipelines(c *gin.Context) { repo := session.Repo(c) @@ -142,6 +143,15 @@ func GetPipelines(c *gin.Context) { filter.Events = wel } + if status := c.Query("status"); status != "" { + ps := model.StatusValue(status) + if err := ps.Validate(); err != nil { + _ = c.AbortWithError(http.StatusBadRequest, err) + return + } + filter.Status = ps + } + if before := c.Query("before"); before != "" { beforeDt, err := time.Parse(time.RFC3339, before) if err != nil { diff --git a/server/model/const.go b/server/model/const.go index 0707473b8..e37171259 100644 --- a/server/model/const.go +++ b/server/model/const.go @@ -66,6 +66,17 @@ const ( StatusCreated StatusValue = "created" // created / internal use only ) +var ErrInvalidStatusValue = errors.New("invalid status value") + +func (s StatusValue) Validate() error { + switch s { + case StatusSkipped, StatusPending, StatusRunning, StatusSuccess, StatusFailure, StatusKilled, StatusError, StatusBlocked, StatusDeclined, StatusCreated: + return nil + default: + return fmt.Errorf("%w: %s", ErrInvalidStatusValue, s) + } +} + // SCMKind represent different version control systems. type SCMKind string // @name SCMKind diff --git a/server/model/pipeline.go b/server/model/pipeline.go index 85270ce19..6268e08a6 100644 --- a/server/model/pipeline.go +++ b/server/model/pipeline.go @@ -66,6 +66,7 @@ type PipelineFilter struct { Branch string Events []WebhookEvent RefContains string + Status StatusValue } // IsMultiPipeline checks if step list contain more than one parent step. diff --git a/server/store/datastore/pipeline.go b/server/store/datastore/pipeline.go index 33a68e5bb..9a32bf482 100644 --- a/server/store/datastore/pipeline.go +++ b/server/store/datastore/pipeline.go @@ -70,6 +70,10 @@ func (s storage) GetPipelineList(repo *model.Repo, p *model.ListOptions, f *mode cond = cond.And(builder.Eq{"branch": f.Branch}) } + if f.Status != "" { + cond = cond.And(builder.Eq{"status": f.Status}) + } + if len(f.Events) != 0 { cond = cond.And(builder.In("event", f.Events)) } diff --git a/server/store/datastore/pipeline_test.go b/server/store/datastore/pipeline_test.go index fa18a085d..3382faf73 100644 --- a/server/store/datastore/pipeline_test.go +++ b/server/store/datastore/pipeline_test.go @@ -277,6 +277,35 @@ func TestPipelines(t *testing.T) { g.Assert(pipelines[0].ID).Equal(pipeline1.ID) g.Assert(pipelines[0].RepoID).Equal(pipeline1.RepoID) }) + + g.It("Should get pipelines filtered by status", func() { + pipeline1 := &model.Pipeline{ + RepoID: repo.ID, + Status: model.StatusSuccess, + } + pipeline2 := &model.Pipeline{ + RepoID: repo.ID, + Status: model.StatusFailure, + } + pipeline3 := &model.Pipeline{ + RepoID: repo.ID, + Status: model.StatusRunning, + } + err1 := store.CreatePipeline(pipeline1, []*model.Step{}...) + g.Assert(err1).IsNil() + err2 := store.CreatePipeline(pipeline2, []*model.Step{}...) + g.Assert(err2).IsNil() + err3 := store.CreatePipeline(pipeline3, []*model.Step{}...) + g.Assert(err3).IsNil() + + pipelines, err := store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ + Status: model.StatusSuccess, + }) + g.Assert(err).IsNil() + g.Assert(len(pipelines)).Equal(1) + g.Assert(pipelines[0].ID).Equal(pipeline1.ID) + g.Assert(pipelines[0].Status).Equal(model.StatusSuccess) + }) }) }