github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/validator/patch.go (about) 1 package validator 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 7 "github.com/evergreen-ci/evergreen" 8 "github.com/evergreen-ci/evergreen/model" 9 "github.com/evergreen-ci/evergreen/model/patch" 10 "github.com/evergreen-ci/evergreen/thirdparty" 11 "github.com/pkg/errors" 12 ) 13 14 // GetPatchedProject creates and validates a project created by fetching latest commit information from GitHub 15 // and applying the patch to the latest remote configuration. The error returned can be a validation error. 16 func GetPatchedProject(p *patch.Patch, settings *evergreen.Settings) (*model.Project, error) { 17 if p.Version != "" { 18 return nil, errors.Errorf("Patch %v already finalized", p.Version) 19 } 20 projectRef, err := model.FindOneProjectRef(p.Project) 21 if err != nil { 22 return nil, errors.WithStack(err) 23 } 24 25 // try to get the remote project file data at the requested revision 26 var projectFileBytes []byte 27 projectFileURL := thirdparty.GetGithubFileURL( 28 projectRef.Owner, 29 projectRef.Repo, 30 projectRef.RemotePath, 31 p.Githash, 32 ) 33 githubFile, err := thirdparty.GetGithubFile(settings.Credentials["github"], projectFileURL) 34 if err != nil { 35 // if the project file doesn't exist, but our patch includes a project file, 36 // we try to apply the diff and proceed. 37 if !(p.ConfigChanged(projectRef.RemotePath) && thirdparty.IsFileNotFound(err)) { 38 // return an error if the github error is network/auth-related or we aren't patching the config 39 return nil, errors.Wrapf(err, "Could not get github file at %v", projectFileURL) 40 } 41 } else { 42 // we successfully got the project file in base64, so we decode it 43 projectFileBytes, err = base64.StdEncoding.DecodeString(githubFile.Content) 44 if err != nil { 45 return nil, errors.Wrapf(err, "Could not decode github file at %v", projectFileURL) 46 } 47 } 48 49 project := &model.Project{} 50 51 // if the patched config exists, use that as the project file bytes. 52 if p.PatchedConfig != "" { 53 projectFileBytes = []byte(p.PatchedConfig) 54 } 55 56 // apply remote configuration patch if needed 57 if p.ConfigChanged(projectRef.RemotePath) && p.PatchedConfig == "" { 58 project, err = model.MakePatchedConfig(p, projectRef.RemotePath, string(projectFileBytes)) 59 if err != nil { 60 return nil, errors.Wrapf(err, "Could not patch remote configuration file") 61 } 62 // overwrite project fields with the project ref to disallow tracking a 63 // different project or doing other crazy things via config patches 64 verrs, err := CheckProjectSyntax(project) 65 if err != nil { 66 return nil, errors.WithStack(err) 67 } 68 69 if len(verrs) != 0 { 70 var message string 71 for _, err := range verrs { 72 message += fmt.Sprintf("\n\t=> %+v", err) 73 } 74 return nil, errors.New(message) 75 } 76 } else { 77 // configuration is not patched 78 if err = model.LoadProjectInto(projectFileBytes, projectRef.Identifier, project); err != nil { 79 return nil, errors.WithStack(err) 80 } 81 } 82 return project, nil 83 }