Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api): load runs with searchWorkflows #5201

Merged
merged 1 commit into from
May 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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