// Returns a JSON response with the marshalled output of the version // specified in the request. func (restapi restAPI) getVersionInfo(w http.ResponseWriter, r *http.Request) { versionId := mux.Vars(r)["version_id"] srcVersion, err := version.FindOne(version.ById(versionId)) if err != nil || srcVersion == nil { msg := fmt.Sprintf("Error finding version '%v'", versionId) statusCode := http.StatusNotFound if err != nil { evergreen.Logger.Logf(slogger.ERROR, "%v: %v", msg, err) statusCode = http.StatusInternalServerError } restapi.WriteJSON(w, statusCode, responseError{Message: msg}) return } destVersion := &restVersion{} // Copy the contents from the database into our local version type err = angier.TransferByFieldNames(srcVersion, destVersion) if err != nil { msg := fmt.Sprintf("Error finding version '%v'", versionId) evergreen.Logger.Logf(slogger.ERROR, "%v: %v", msg, err) restapi.WriteJSON(w, http.StatusInternalServerError, responseError{Message: msg}) return } for _, buildStatus := range srcVersion.BuildVariants { destVersion.BuildVariants = append(destVersion.BuildVariants, buildStatus.BuildVariant) evergreen.Logger.Logf(slogger.ERROR, "adding BuildVariant %v", buildStatus.BuildVariant) } restapi.WriteJSON(w, http.StatusOK, destVersion) return }
// Returns a JSON response with the marshalled output of the build // specified in the request. func (restapi *restAPI) getBuildInfo(w http.ResponseWriter, r *http.Request) { buildId := mux.Vars(r)["build_id"] srcBuild, err := build.FindOne(build.ById(buildId)) if err != nil || srcBuild == nil { msg := fmt.Sprintf("Error finding build '%v'", buildId) statusCode := http.StatusNotFound if err != nil { evergreen.Logger.Logf(slogger.ERROR, "%v: %v", msg, err) statusCode = http.StatusInternalServerError } restapi.WriteJSON(w, statusCode, responseError{Message: msg}) return } destBuild := &restBuild{} // Copy the contents from the database into our local build type err = angier.TransferByFieldNames(srcBuild, destBuild) if err != nil { msg := fmt.Sprintf("Error finding build '%v'", buildId) evergreen.Logger.Logf(slogger.ERROR, "%v: %v", msg, err) restapi.WriteJSON(w, http.StatusInternalServerError, responseError{Message: msg}) return } destBuild.Tasks = make(buildStatusByTask, len(srcBuild.Tasks)) for _, task := range srcBuild.Tasks { status := buildStatus{ Id: task.Id, Status: task.Status, TimeTaken: task.TimeTaken, } destBuild.Tasks[task.DisplayName] = status } restapi.WriteJSON(w, http.StatusOK, destBuild) return }
// Returns a JSON response with the marshalled output of the task // specified in the request. func (restapi restAPI) getTaskInfo(w http.ResponseWriter, r *http.Request) { taskId := mux.Vars(r)["task_id"] srcTask, err := model.FindTask(taskId) if err != nil || srcTask == nil { msg := fmt.Sprintf("Error finding task '%v'", taskId) statusCode := http.StatusNotFound if err != nil { evergreen.Logger.Logf(slogger.ERROR, "%v: %v", msg, err) statusCode = http.StatusInternalServerError } restapi.WriteJSON(w, statusCode, responseError{Message: msg}) return } destTask := &task{} // Copy the contents from the database into our local task type err = angier.TransferByFieldNames(srcTask, destTask) if err != nil { msg := fmt.Sprintf("Error finding task '%v'", taskId) evergreen.Logger.Logf(slogger.ERROR, "%v: %v", msg, err) restapi.WriteJSON(w, http.StatusInternalServerError, responseError{Message: msg}) return } // Copy over the status details destTask.StatusDetails.TimedOut = srcTask.StatusDetails.TimedOut destTask.StatusDetails.TimeoutStage = srcTask.StatusDetails.TimeoutStage // Copy over the test results destTask.TestResults = make(taskTestResultsByName, len(srcTask.TestResults)) for _, _testResult := range srcTask.TestResults { numSecs := _testResult.EndTime - _testResult.StartTime testResult := taskTestResult{ Status: _testResult.Status, TimeTaken: time.Duration(numSecs * float64(time.Second)), Logs: taskTestLogURL{_testResult.URL}, } destTask.TestResults[_testResult.TestFile] = testResult } // Copy over artifacts and binaries entries, err := artifact.FindAll(artifact.ByTaskId(taskId)) if err != nil { msg := fmt.Sprintf("Error finding task '%v'", taskId) evergreen.Logger.Logf(slogger.ERROR, "%v: %v", msg, err) restapi.WriteJSON(w, http.StatusInternalServerError, responseError{Message: msg}) return } for _, entry := range entries { for _, _file := range entry.Files { file := taskFile{ Name: _file.Name, URL: _file.Link, } destTask.Files = append(destTask.Files, file) } } restapi.WriteJSON(w, http.StatusOK, destTask) return }
// Creates a copy of `current`, with instances of ${matrixParameterName} in // top level string and slice of strings fields replaced by the value specified // in matrixParameterValues func expandBuildVariantMatrixParameters(project *Project, current BuildVariant, matrixParameterValues []MatrixParameterValue) (*BuildVariant, error) { // Create a new build variant with the same parameters newBv := BuildVariant{} err := angier.TransferByFieldNames(¤t, &newBv) if err != nil { return nil, err } newBv.Expansions = make(map[string]string) // Make sure to copy over expansions for k, v := range current.Expansions { newBv.Expansions[k] = v } // Convert parameter value state into a map for use with expansions matrixParameterMap := make(map[string]string) for i, parameter := range project.BuildVariantMatrix.MatrixParameters { matrixParameterMap[parameter.Name] = matrixParameterValues[i].Value } matrixParameterExpansions := command.NewExpansions(matrixParameterMap) // Iterate over all fields numFields := reflect.TypeOf(newBv).NumField() for fieldIndex := 0; fieldIndex < numFields; fieldIndex++ { // Expand matrix parameters in top level string fields if reflect.TypeOf(newBv).Field(fieldIndex).Type.Kind() == reflect.String { val := reflect.ValueOf(&newBv).Elem().Field(fieldIndex).String() val, err := matrixParameterExpansions.ExpandString(val) if err != nil { return nil, err } reflect.ValueOf(&newBv).Elem().Field(fieldIndex).SetString(val) } // Expand matrix parameters in top level slices of strings if reflect.TypeOf(newBv).Field(fieldIndex).Type == reflect.SliceOf(reflect.TypeOf("")) { slice := reflect.ValueOf(&newBv).Elem().Field(fieldIndex) newSlice := []string{} for arrayIndex := 0; arrayIndex < slice.Len(); arrayIndex++ { // Expand matrix parameters for each individual element of the slice val := slice.Index(arrayIndex).String() val, err := matrixParameterExpansions.ExpandString(val) if err != nil { return nil, err } newSlice = append(newSlice, val) } reflect.ValueOf(&newBv).Elem().Field(fieldIndex).Set(reflect.ValueOf(newSlice)) } } // First, attach all conditional expansions (i.e. expansions associated with // a given parameter value) for _, value := range matrixParameterValues { for k, v := range value.Expansions { newBv.Expansions[k] = v } } // Then, expand matrix parameters in all expansions for key, expansion := range newBv.Expansions { expansion, err := matrixParameterExpansions.ExpandString(expansion) if err != nil { return nil, err } newBv.Expansions[key] = expansion } // Build variant matrix parameter values are stored in the build variant buildVariantMatrixParameterValues := make(map[string]string) for i, matrixParameter := range project.BuildVariantMatrix.MatrixParameters { buildVariantMatrixParameterValues[matrixParameter.Name] = matrixParameterValues[i].Value } newBv.MatrixParameterValues = buildVariantMatrixParameterValues return &newBv, nil }
func ValidateAndFinalize(p *patch.Patch, settings *evergreen.Settings) (*version.Version, error) { if p.Version != "" { return nil, fmt.Errorf("Patch %v already finalized", p.Version) } projectRef, err := model.FindOneProjectRef(p.Project) if err != nil { return nil, err } gitCommit, err := thirdparty.GetCommitEvent( settings.Credentials["github"], projectRef.Owner, projectRef.Repo, p.Githash, ) if err != nil { return nil, fmt.Errorf("Couldn't fetch commit information: %v", err) } if gitCommit == nil { return nil, fmt.Errorf("Couldn't fetch commit information: git commit" + " doesn't exist?") } // get the remote file at the requested revision projectFileURL := thirdparty.GetGithubFileURL( projectRef.Owner, projectRef.Repo, projectRef.RemotePath, p.Githash, ) githubFile, err := thirdparty.GetGithubFile( settings.Credentials["github"], projectFileURL, ) if err != nil { return nil, fmt.Errorf("Could not get github file at %v: %v", projectFileURL, err) } projectFileBytes, err := base64.StdEncoding.DecodeString(githubFile.Content) if err != nil { return nil, fmt.Errorf("Could not decode github file at %v: %v", projectFileURL, err) } project := &model.Project{} if err = model.LoadProjectInto(projectFileBytes, projectRef.Identifier, project); err != nil { return nil, err } // apply remote configuration patch if needed if p.ConfigChanged(projectRef.RemotePath) { project, err = model.MakePatchedConfig(p, projectRef.RemotePath, string(projectFileBytes)) if err != nil { return nil, fmt.Errorf("Could not patch remote configuration file: %v", err) } // overwrite project fields with the project ref to disallow tracking a // different project or doing other crazy things via config patches if err = angier.TransferByFieldNames(projectRef, project); err != nil { return nil, fmt.Errorf("Could not merge project Ref ref into project: %v", err) } errs := CheckProjectSyntax(project) if len(errs) != 0 { var message string for _, err := range errs { message += fmt.Sprintf("\n\t=> %v", err) } return nil, fmt.Errorf(message) } } else { // overwrite project fields with the project ref to disallow tracking a // different project or doing other crazy things via config patches if err = angier.TransferByFieldNames(projectRef, project); err != nil { return nil, fmt.Errorf("Could not merge project Ref ref into project: %v", err) } } return model.FinalizePatch(p, gitCommit, settings, project) }