// Create and return the waterfall data we need to render the page. // Http handler for the waterfall page func (uis *UIServer) waterfallPage(w http.ResponseWriter, r *http.Request) { projCtx := MustHaveProjectContext(r) if projCtx.Project == nil { uis.ProjectNotFound(projCtx, w, r) return } skip, err := skipValue(r) if err != nil { skip = 0 } finalData := waterfallData{} // first, get all of the versions and variants we will need vvData, err := getVersionsAndVariants(skip, VersionItemsToCreate, projCtx.Project) if err != nil { uis.LoggedError(w, r, http.StatusInternalServerError, err) return } var wfv waterfallVersions = vvData.Versions sort.Sort(wfv) finalData.Versions = wfv sort.Sort(vvData.BuildVariants) rows := []waterfallRow{} for _, bv := range vvData.BuildVariants { rows = append(rows, vvData.Rows[bv.Id]) } finalData.Rows = rows // compute the total number of versions that exist finalData.TotalVersions, err = version.Count(version.ByProjectId(projCtx.Project.Identifier)) if err != nil { uis.LoggedError(w, r, http.StatusInternalServerError, err) return } // compute the number of versions on the previous page finalData.PreviousPageCount, err = countOnPreviousPage(skip, VersionItemsToCreate, projCtx.Project) if err != nil { uis.LoggedError(w, r, http.StatusInternalServerError, err) return } // add in the skip value finalData.CurrentSkip = skip // pass it the current time finalData.CurrentTime = time.Now().UnixNano() uis.WriteHTML(w, http.StatusOK, struct { ProjectData projectContext User *user.DBUser Data waterfallData }{projCtx, GetUser(r), finalData}, "base", "waterfall.html", "base_angular.html", "menu.html") }
func getTimelineData(projectName, requester string, versionsToSkip, versionsPerPage int) (*timelineData, error) { data := &timelineData{} // get the total number of versions in the database (used for pagination) totalVersions, err := version.Count(version.ByProjectId(projectName)) if err != nil { return nil, err } data.TotalVersions = totalVersions q := version.ByMostRecentForRequester(projectName, requester).WithoutFields(version.ConfigKey). Skip(versionsToSkip * versionsPerPage).Limit(versionsPerPage) // get the most recent versions, to display in their entirety on the page versionsFromDB, err := version.Find(q) if err != nil { return nil, err } // create the necessary uiVersion struct for each version uiVersions := make([]uiVersion, len(versionsFromDB)) for versionIdx, version := range versionsFromDB { versionAsUI := uiVersion{Version: version} uiVersions[versionIdx] = versionAsUI buildIds := version.BuildIds dbBuilds, err := build.Find(build.ByIds(buildIds)) if err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Ids: %v", buildIds) } buildsMap := make(map[string]build.Build) for _, dbBuild := range dbBuilds { buildsMap[dbBuild.Id] = dbBuild } uiBuilds := make([]uiBuild, len(dbBuilds)) for buildIdx, buildId := range buildIds { build := buildsMap[buildId] buildAsUI := uiBuild{Build: build} uiBuilds[buildIdx] = buildAsUI } versionAsUI.Builds = uiBuilds uiVersions[versionIdx] = versionAsUI } data.Versions = uiVersions return data, nil }
// Create and return the waterfall data we need to render the page. // Http handler for the waterfall page func (uis *UIServer) waterfallPage(w http.ResponseWriter, r *http.Request) { projCtx := MustHaveProjectContext(r) if projCtx.Project == nil { uis.ProjectNotFound(projCtx, w, r) return } skip, err := skipValue(r) if err != nil { skip = 0 } finalData := waterfallData{} // first, get all of the versions and variants we will need finalData.Versions, finalData.BuildVariants, err = getVersionsAndVariants(skip, VersionItemsToCreate, projCtx.Project) if err != nil { uis.LoggedError(w, r, http.StatusInternalServerError, err) return } // compute the total number of versions that exist finalData.TotalVersions, err = version.Count(version.ByProjectId(projCtx.Project.Identifier)) if err != nil { uis.LoggedError(w, r, http.StatusInternalServerError, err) return } // compute the number of versions on the previous page finalData.PreviousPageCount, err = countOnPreviousPage(skip, VersionItemsToCreate, projCtx.Project) if err != nil { uis.LoggedError(w, r, http.StatusInternalServerError, err) return } // add in the skip value finalData.CurrentSkip = skip uis.WriteHTML(w, http.StatusOK, struct { ProjectData projectContext User *user.DBUser Data waterfallData }{projCtx, GetUser(r), finalData}, "base", "waterfall.html", "base_angular.html", "menu.html") }
// Helper function to fetch a group of versions and their associated builds. // Returns the versions themselves, as well as a map of version id -> the // builds that are a part of the version (unsorted). func fetchVersionsAndAssociatedBuilds(project *model.Project, skip int, numVersions int) ([]version.Version, map[string][]build.Build, error) { // fetch the versions from the db versionsFromDB, err := version.Find(version.ByProjectId(project.Identifier). WithFields( version.RevisionKey, version.ErrorsKey, version.WarningsKey, version.IgnoredKey, version.MessageKey, version.AuthorKey, version.RevisionOrderNumberKey, version.CreateTimeKey, ).Sort([]string{"-" + version.RevisionOrderNumberKey}).Skip(skip).Limit(numVersions)) if err != nil { return nil, nil, fmt.Errorf("error fetching versions from database: %v", err) } // create a slice of the version ids (used to fetch the builds) versionIds := make([]string, 0, len(versionsFromDB)) for _, v := range versionsFromDB { versionIds = append(versionIds, v.Id) } // fetch all of the builds (with only relevant fields) buildsFromDb, err := build.Find( build.ByVersions(versionIds). WithFields(build.BuildVariantKey, build.TasksKey, build.VersionKey)) if err != nil { return nil, nil, fmt.Errorf("error fetching builds from database: %v", err) } // group the builds by version buildsByVersion := map[string][]build.Build{} for _, build := range buildsFromDb { buildsByVersion[build.Version] = append(buildsByVersion[build.Version], build) } return versionsFromDB, buildsByVersion, nil }