Skip to content

Commit

Permalink
feat(api): load runs with searchWorkflows (#5201)
Browse files Browse the repository at this point in the history
Signed-off-by: francois  samin <[email protected]>
  • Loading branch information
fsamin authored May 26, 2020
1 parent 0372f01 commit 8cd9356
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 35 deletions.
20 changes: 7 additions & 13 deletions engine/api/router_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ func FormString(r *http.Request, s string) string {
return r.FormValue(s)
}

// FormIntr return a int
func FormInt(r *http.Request, s string) int {
v := r.FormValue(s)
i, _ := strconv.Atoi(v)
return i
}

// QueryString return a string from a query parameter
func QueryString(r *http.Request, s string) string {
return r.FormValue(s)
Expand Down Expand Up @@ -156,19 +163,6 @@ func QuerySort(r *http.Request) (map[string]SortOrder, error) {
return res, nil
}

// FormInt return a int from query params
func FormInt(r *http.Request, s string) (int, error) {
stringValue := FormString(r, s)
if stringValue == "" {
return 0, nil
}
i, err := strconv.Atoi(stringValue)
if err != nil {
return i, sdk.WrapError(sdk.ErrInvalidNumber, "FormInt> %s is not a integer", stringValue)
}
return i, nil
}

// requestVarInt return int value for a var in Request
func requestVarInt(r *http.Request, s string) (int64, error) {
vars := mux.Vars(r)
Expand Down
5 changes: 1 addition & 4 deletions engine/api/timeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ func (api *API) getTimelineHandler() service.Handler {
consumer := getAPIConsumer(ctx)

// Get index of the first element to return
currentItem, err := FormInt(r, "currentItem")
if err != nil {
return sdk.WrapError(err, "invalid format for current item")
}
currentItem := FormInt(r, "currentItem")

// Get workflow to mute
timelineFilter, err := user.LoadTimelineFilter(api.mustDB(), consumer.AuthentifiedUser.ID)
Expand Down
9 changes: 5 additions & 4 deletions engine/api/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -771,10 +771,11 @@ func (api *API) getWorkflowNotificationsConditionsHandler() service.Handler {
func (api *API) getSearchWorkflowHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
var dao workflow.WorkflowDAO
dao.Filters.ProjectKey = r.FormValue("project")
dao.Filters.WorkflowName = r.FormValue("name")
dao.Filters.VCSServer = r.FormValue("vcs")
dao.Filters.ApplicationRepository = r.FormValue("repository")
dao.Filters.ProjectKey = FormString(r, "project")
dao.Filters.WorkflowName = FormString(r, "name")
dao.Filters.VCSServer = FormString(r, "vcs")
dao.Filters.ApplicationRepository = FormString(r, "repository")
dao.Loaders.WithRuns = FormInt(r, "runs")
dao.Loaders.WithFavoritesForUserID = getAPIConsumer(ctx).AuthentifiedUserID

groupIDS := getAPIConsumer(ctx).GetGroupIDs()
Expand Down
41 changes: 29 additions & 12 deletions engine/api/workflow/dao_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/fsamin/go-dump"
"github.com/go-gorp/gorp"
"github.com/lib/pq"
"go.opencensus.io/stats"

"github.com/ovh/cds/engine/api/database/gorpmapping"
Expand Down Expand Up @@ -238,6 +239,15 @@ func LoadLastRun(db gorp.SqlExecutor, projectkey, workflowname string, loadOpts
return loadRun(db, loadOpts, query, projectkey, workflowname)
}

// LoadLastRuns returns the last run per workflowIDs
func LoadLastRuns(db gorp.SqlExecutor, workflowIDs []int64, limit int) ([]sdk.WorkflowRun, error) {
query := fmt.Sprintf(`select %s
from workflow_run
where workflow_run.workflow_id = ANY($1)
order by workflow_run.workflow_id, workflow_run.num desc limit $2`, wfRunfields)
return loadRuns(db, query, pq.Int64Array(workflowIDs), limit)
}

// LoadRun returns a specific run
func LoadRun(ctx context.Context, db gorp.SqlExecutor, projectkey, workflowname string, number int64, loadOpts LoadRunOptions) (*sdk.WorkflowRun, error) {
_, end := observability.Span(ctx, "workflow.LoadRun",
Expand Down Expand Up @@ -284,6 +294,22 @@ func LoadAndLockRunByJobID(db gorp.SqlExecutor, id int64, loadOpts LoadRunOption
return loadRun(db, loadOpts, query, id)
}

func loadRuns(db gorp.SqlExecutor, query string, args ...interface{}) ([]sdk.WorkflowRun, error) {
runs := []Run{}
if _, err := db.Select(&runs, query, args...); err != nil {
return nil, sdk.WrapError(err, "Unable to load runs")
}
wruns := make([]sdk.WorkflowRun, len(runs))
for i := range runs {
wr := sdk.WorkflowRun(runs[i])
if err := loadRunTags(db, &wr); err != nil {
return nil, sdk.WrapError(err, "Unable to load tags")
}
wruns[i] = wr
}
return wruns, nil
}

//LoadRuns loads all runs
//It returns runs, offset, limit count and an error
func LoadRuns(db gorp.SqlExecutor, projectkey, workflowname string, offset, limit int, tagFilter map[string]string) ([]sdk.WorkflowRun, int, int, int, error) {
Expand Down Expand Up @@ -367,18 +393,9 @@ func LoadRuns(db gorp.SqlExecutor, projectkey, workflowname string, offset, limi
args = append(args, strings.Join(tags, ","))
}

runs := []Run{}
if _, err := db.Select(&runs, query, args...); err != nil {
return nil, 0, 0, 0, sdk.WrapError(errc, "Unable to load runs")
}
wruns := make([]sdk.WorkflowRun, len(runs))
for i := range runs {
wr := sdk.WorkflowRun(runs[i])
if err := loadRunTags(db, &wr); err != nil {
return nil, 0, 0, 0, sdk.WrapError(err, "Unable to load tags")
}

wruns[i] = wr
wruns, err := loadRuns(db, query, args...)
if err != nil {
return nil, 0, 0, 0, err
}

return wruns, offset, limit, int(count), nil
Expand Down
31 changes: 31 additions & 0 deletions engine/api/workflow/factory_dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type LoadAllWorkflowsOptionsLoaders struct {
WithLabels bool
WithAudits bool
WithFavoritesForUserID string
WithRuns int
}

type WorkflowDAO struct {
Expand Down Expand Up @@ -282,6 +283,13 @@ func (dao WorkflowDAO) GetLoaders() []gorpmapping.GetOptionFunc {
})
}

if dao.Loaders.WithRuns != 0 {
loaders = append(loaders, func(db gorp.SqlExecutor, i interface{}) error {
ws := i.(*[]Workflow)
return dao.withRuns(db, ws, dao.Loaders.WithRuns)
})
}

loaders = append(loaders,
func(db gorp.SqlExecutor, i interface{}) error {
ws := i.(*[]Workflow)
Expand Down Expand Up @@ -628,6 +636,29 @@ func (dao WorkflowDAO) withLabels(db gorp.SqlExecutor, ws *[]Workflow) error {
return nil
}

func (dao WorkflowDAO) withRuns(db gorp.SqlExecutor, ws *[]Workflow, limit int) error {
var ids = make([]int64, 0, len(*ws))
for _, w := range *ws {
ids = append(ids, w.ID)
}

runs, err := LoadLastRuns(db, ids, limit)
if err != nil {
return err
}

for x := range *ws {
w := &(*ws)[x]
for _, run := range runs {
if w.ID == run.WorkflowID {
w.Runs = append(w.Runs, run)
}
}
}

return nil
}

func (dao WorkflowDAO) withFavorites(db gorp.SqlExecutor, ws *[]Workflow, userID string) error {
workflowIDs, err := UserFavoriteWorkflowIDs(db, userID)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions engine/api/workflow/factory_dao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func TestLoadAllWorkflows(t *testing.T) {
WithIntegrations: true,
WithPipelines: true,
WithTemplate: true,
WithRuns: 10,
},
},
}
Expand Down
5 changes: 4 additions & 1 deletion engine/api/workflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1982,7 +1982,10 @@ func Test_getSearchWorkflowHandler(t *testing.T) {
BuitinConsumerAuthenticationToken: jws,
})

wfs, err := sdkclientAdmin.WorkflowSearch(cdsclient.WithQueryParameter("repository", "ovh/"+repofullName))
wfs, err := sdkclientAdmin.WorkflowSearch(
cdsclient.WithQueryParameter("repository", "ovh/"+repofullName),
cdsclient.WithQueryParameter("runs", "10"),
)
require.NoError(t, err)
require.Len(t, wfs, 1)
require.Equal(t, wf.Name, wfs[0].Name)
Expand Down
2 changes: 1 addition & 1 deletion engine/api/workflow_trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (api *API) getWorkflowTriggerConditionHandler() service.Handler {
vars := mux.Vars(r)
key := vars["key"]
name := vars["permWorkflowName"]
id, _ := FormInt(r, "nodeID")
id := FormInt(r, "nodeID")

proj, err := project.Load(api.mustDB(), key, project.LoadOptions.WithVariables, project.LoadOptions.WithIntegrations)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions sdk/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type Workflow struct {
FromTemplate string `json:"from_template,omitempty" db:"-" cli:"-"`
TemplateUpToDate bool `json:"template_up_to_date,omitempty" db:"-" cli:"-"`
URLs URL `json:"urls" yaml:"-" db:"-" cli:"-"`
Runs []WorkflowRun `json:"runs,omitempty" yaml:"-" db:"-" cli:"-"`
}

type PurgeTags []string
Expand Down

0 comments on commit 8cd9356

Please sign in to comment.