From 123969c7e1608777f15d2fe7a6bcbea51c33fe05 Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Fri, 8 Nov 2024 19:08:20 +0000 Subject: [PATCH] feat: [PIPE-23137]: updated executionInfo struct with more data and added lastExecutions to list space pipelines API (#2958) * fixed go lint * fixed go lint * feat: [CODE-23137]: added execution summary data to list space pipelines API --- app/api/controller/space/list_pipelines.go | 14 ++++++++- app/api/handler/space/list_pipelines.go | 7 ++++- app/api/openapi/pipeline.go | 36 ++++++++++++++++++++-- app/api/openapi/space.go | 3 +- app/api/request/pipeline.go | 8 ++--- app/store/database.go | 4 +-- app/store/database/execution.go | 16 ++++++++-- app/store/database/pipeline.go | 4 +-- types/execution.go | 11 +++++-- 9 files changed, 84 insertions(+), 19 deletions(-) diff --git a/app/api/controller/space/list_pipelines.go b/app/api/controller/space/list_pipelines.go index c451f1621..23f1c6e72 100644 --- a/app/api/controller/space/list_pipelines.go +++ b/app/api/controller/space/list_pipelines.go @@ -30,7 +30,7 @@ func (c *Controller) ListPipelines( ctx context.Context, session *auth.Session, spaceRef string, - filter types.ListQueryFilter, + filter types.ListPipelinesFilter, ) ([]*types.Pipeline, int64, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { @@ -49,6 +49,18 @@ func (c *Controller) ListPipelines( return fmt.Errorf("failed to list pipelines in space: %w", err) } + pipelineIDs := make([]int64, len(pipelines)) + for i, pipeline := range pipelines { + pipelineIDs[i] = pipeline.ID + } + execs, err := c.executionStore.ListByPipelineIDs(ctx, pipelineIDs, filter.LastExecutions) + if err != nil { + return fmt.Errorf("failed to list executions by pipeline IDs: %w", err) + } + for _, pipeline := range pipelines { + pipeline.LastExecutions = execs[pipeline.ID] + } + if filter.Page == 1 && len(pipelines) < filter.Size { count = int64(len(pipelines)) return nil diff --git a/app/api/handler/space/list_pipelines.go b/app/api/handler/space/list_pipelines.go index ee56129c2..fceb36946 100644 --- a/app/api/handler/space/list_pipelines.go +++ b/app/api/handler/space/list_pipelines.go @@ -31,7 +31,12 @@ func HandleListPipelines(spaceCtrl *space.Controller) http.HandlerFunc { render.TranslatedUserError(ctx, w, err) return } - filter := request.ParseListQueryFilterFromRequest(r) + + filter, err := request.ParseListPipelinesFilterFromRequest(r) + if err != nil { + render.TranslatedUserError(ctx, w, err) + } + pipelines, totalCount, err := spaceCtrl.ListPipelines(ctx, session, spaceRef, filter) if err != nil { render.TranslatedUserError(ctx, w, err) diff --git a/app/api/openapi/pipeline.go b/app/api/openapi/pipeline.go index c9f13c82b..c20930f24 100644 --- a/app/api/openapi/pipeline.go +++ b/app/api/openapi/pipeline.go @@ -85,6 +85,20 @@ type updatePipelineRequest struct { pipeline.UpdateInput } +var queryParameterQueryPipeline = openapi3.ParameterOrRef{ + Parameter: &openapi3.Parameter{ + Name: request.QueryParamQuery, + In: openapi3.ParameterInQuery, + Description: ptr.String("The substring which is used to filter the pipelines by their names."), + Required: ptr.Bool(false), + Schema: &openapi3.SchemaOrRef{ + Schema: &openapi3.Schema{ + Type: ptrSchemaType(openapi3.SchemaTypeString), + }, + }, + }, +} + var queryParameterLatest = openapi3.ParameterOrRef{ Parameter: &openapi3.Parameter{ Name: request.QueryParamLatest, @@ -93,7 +107,24 @@ var queryParameterLatest = openapi3.ParameterOrRef{ Required: ptr.Bool(false), Schema: &openapi3.SchemaOrRef{ Schema: &openapi3.Schema{ - Type: ptrSchemaType(openapi3.SchemaTypeBoolean), + Type: ptrSchemaType(openapi3.SchemaTypeBoolean), + Default: ptrptr(false), + }, + }, + }, +} + +var queryParameterLastExecutions = openapi3.ParameterOrRef{ + Parameter: &openapi3.Parameter{ + Name: request.QueryParamLastExecutions, + In: openapi3.ParameterInQuery, + Description: ptr.String("The number of last executions to be returned"), + Required: ptr.Bool(false), + Schema: &openapi3.SchemaOrRef{ + Schema: &openapi3.Schema{ + Type: ptrSchemaType(openapi3.SchemaTypeInteger), + Default: ptrptr(10), + Minimum: ptr.Float64(1), }, }, }, @@ -128,7 +159,8 @@ func pipelineOperations(reflector *openapi3.Reflector) { opPipelines := openapi3.Operation{} opPipelines.WithTags("pipeline") opPipelines.WithMapOfAnything(map[string]interface{}{"operationId": "listPipelines"}) - opPipelines.WithParameters(queryParameterQueryRepo, QueryParameterPage, QueryParameterLimit, queryParameterLatest) + opPipelines.WithParameters(queryParameterQueryPipeline, QueryParameterPage, + QueryParameterLimit, queryParameterLatest, queryParameterLastExecutions) _ = reflector.SetRequest(&opPipelines, new(repoRequest), http.MethodGet) _ = reflector.SetJSONResponse(&opPipelines, []types.Pipeline{}, http.StatusOK) _ = reflector.SetJSONResponse(&opPipelines, new(usererror.Error), http.StatusInternalServerError) diff --git a/app/api/openapi/space.go b/app/api/openapi/space.go index 9f1c9c98a..b9c1127e4 100644 --- a/app/api/openapi/space.go +++ b/app/api/openapi/space.go @@ -374,7 +374,8 @@ func spaceOperations(reflector *openapi3.Reflector) { opPipelines := openapi3.Operation{} opPipelines.WithTags("space") opPipelines.WithMapOfAnything(map[string]interface{}{"operationId": "listSpacePipelines"}) - opPipelines.WithParameters(queryParameterQueryRepo, QueryParameterPage, QueryParameterLimit) + opPipelines.WithParameters(queryParameterQueryPipeline, QueryParameterPage, + QueryParameterLimit, queryParameterLastExecutions) _ = reflector.SetRequest(&opPipelines, new(spaceRequest), http.MethodGet) _ = reflector.SetJSONResponse(&opPipelines, []types.Pipeline{}, http.StatusOK) _ = reflector.SetJSONResponse(&opPipelines, new(usererror.Error), http.StatusUnauthorized) diff --git a/app/api/request/pipeline.go b/app/api/request/pipeline.go index 5cf714758..10adf3f62 100644 --- a/app/api/request/pipeline.go +++ b/app/api/request/pipeline.go @@ -23,11 +23,11 @@ import ( const ( PathParamPipelineIdentifier = "pipeline_identifier" PathParamExecutionNumber = "execution_number" - PathParamLastExecutions = "last_executions" PathParamStageNumber = "stage_number" PathParamStepNumber = "step_number" PathParamTriggerIdentifier = "trigger_identifier" QueryParamLatest = "latest" + QueryParamLastExecutions = "last_executions" QueryParamBranch = "branch" ) @@ -52,8 +52,8 @@ func GetStepNumberFromPath(r *http.Request) (int64, error) { } func GetLatestFromPath(r *http.Request) bool { - v, _ := QueryParam(r, QueryParamLatest) - return v == "true" + l, _ := QueryParamAsBoolOrDefault(r, QueryParamLatest, false) + return l } func GetTriggerIdentifierFromPath(r *http.Request) (string, error) { @@ -61,7 +61,7 @@ func GetTriggerIdentifierFromPath(r *http.Request) (string, error) { } func ParseListPipelinesFilterFromRequest(r *http.Request) (types.ListPipelinesFilter, error) { - lastExecs, err := QueryParamAsPositiveInt64OrDefault(r, PathParamLastExecutions, 10) + lastExecs, err := QueryParamAsPositiveInt64OrDefault(r, QueryParamLastExecutions, 10) if err != nil { return types.ListPipelinesFilter{}, err } diff --git a/app/store/database.go b/app/store/database.go index fa7ad43a9..4ac2896f4 100644 --- a/app/store/database.go +++ b/app/store/database.go @@ -783,10 +783,10 @@ type ( IncrementSeqNum(ctx context.Context, pipeline *types.Pipeline) (*types.Pipeline, error) // ListInSpace lists pipelines in a particular space. - ListInSpace(ctx context.Context, spaceID int64, filter types.ListQueryFilter) ([]*types.Pipeline, error) + ListInSpace(ctx context.Context, spaceID int64, filter types.ListPipelinesFilter) ([]*types.Pipeline, error) // CountInSpace counts pipelines in a particular space. - CountInSpace(ctx context.Context, spaceID int64, filter types.ListQueryFilter) (int64, error) + CountInSpace(ctx context.Context, spaceID int64, filter types.ListPipelinesFilter) (int64, error) } SecretStore interface { diff --git a/app/store/database/execution.go b/app/store/database/execution.go index 0f76d1bc4..e87a60061 100644 --- a/app/store/database/execution.go +++ b/app/store/database/execution.go @@ -131,6 +131,17 @@ const ( ,execution_updated ,execution_version ` + + executionInfoColumns = ` + execution_number + ,execution_pipeline_id + ,execution_status + ,execution_created_by + ,execution_trigger + ,execution_event + ,execution_started + ,execution_finished + ` ) // Find returns an execution given an execution ID. @@ -393,11 +404,10 @@ func (s executionStore) ListByPipelineIDs( maxRows int64, ) (map[int64][]*types.ExecutionInfo, error) { stmt := database.Builder. - Select("execution_number, execution_pipeline_id, execution_status"). + Select(executionInfoColumns). FromSelect( database.Builder. - Select(` - execution_number, execution_pipeline_id, execution_status, + Select(executionInfoColumns+`, ROW_NUMBER() OVER ( PARTITION BY execution_pipeline_id ORDER BY execution_number DESC diff --git a/app/store/database/pipeline.go b/app/store/database/pipeline.go index b735e77c4..40489d822 100644 --- a/app/store/database/pipeline.go +++ b/app/store/database/pipeline.go @@ -219,7 +219,7 @@ func (s *pipelineStore) List( func (s *pipelineStore) ListInSpace( ctx context.Context, spaceID int64, - filter types.ListQueryFilter, + filter types.ListPipelinesFilter, ) ([]*types.Pipeline, error) { const pipelineWithRepoColumns = pipelineColumns + ` ,repo_id @@ -391,7 +391,7 @@ func (s *pipelineStore) Count( func (s *pipelineStore) CountInSpace( ctx context.Context, spaceID int64, - filter types.ListQueryFilter, + filter types.ListPipelinesFilter, ) (int64, error) { stmt := database.Builder. Select("count(*)"). diff --git a/types/execution.go b/types/execution.go index 720f9af02..5d661208d 100644 --- a/types/execution.go +++ b/types/execution.go @@ -72,7 +72,12 @@ type Execution struct { } type ExecutionInfo struct { - Number int64 `db:"execution_number" json:"number"` - PipelineID int64 `db:"execution_pipeline_id" json:"pipeline_id"` - Status enum.CIStatus `db:"execution_status" json:"status"` + Number int64 `db:"execution_number" json:"number"` + PipelineID int64 `db:"execution_pipeline_id" json:"pipeline_id"` + Status enum.CIStatus `db:"execution_status" json:"status"` + CreatedBy int64 `db:"execution_created_by" json:"created_by"` + Trigger string `db:"execution_trigger" json:"trigger,omitempty"` + Event enum.TriggerEvent `db:"execution_event" json:"event,omitempty"` + Started int64 `db:"execution_started" json:"started,omitempty"` + Finished int64 `db:"execution_finished" json:"finished,omitempty"` }