github.com/joshdk/godel@v0.0.0-20170529232908-862138a45aee/apps/distgo/pkg/script/script.go (about) 1 // Copyright 2016 Palantir Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package script 16 17 import ( 18 "fmt" 19 "io" 20 "io/ioutil" 21 "os" 22 "os/exec" 23 24 "github.com/pkg/errors" 25 26 "github.com/palantir/godel/apps/distgo/params" 27 ) 28 29 func Write(buildSpec params.ProductBuildSpec, script string) (name string, cleanup func() error, rErr error) { 30 tmpFile, err := ioutil.TempFile(buildSpec.ProjectDir, "") 31 if err != nil { 32 return "", nil, errors.Wrapf(err, "Failed to create script file") 33 } 34 cleanup = func() error { 35 return os.Remove(tmpFile.Name()) 36 } 37 // clean up unless everything below succeeds 38 runCleanup := true 39 defer func() { 40 if runCleanup { 41 if err := cleanup(); err != nil && rErr == nil { 42 rErr = errors.Wrapf(err, "failed to remove script file %s", tmpFile.Name()) 43 } 44 } 45 }() 46 47 if _, err := tmpFile.WriteString(fmt.Sprintf("#!/bin/bash\n%v", script)); err != nil { 48 return "", nil, errors.Wrapf(err, "Failed to write script file") 49 } 50 51 if err := tmpFile.Close(); err != nil { 52 return "", nil, errors.Wrapf(err, "Failed to close %v", tmpFile.Name()) 53 } 54 55 if err := os.Chmod(tmpFile.Name(), 0755); err != nil { 56 return "", nil, errors.Wrapf(err, "Failed to set file mode of %v to 0755", tmpFile.Name()) 57 } 58 59 runCleanup = false 60 return tmpFile.Name(), cleanup, nil 61 } 62 63 func WriteAndExecute(buildSpec params.ProductBuildSpec, script string, stdOut, stdErr io.Writer, additionalEnvVars map[string]string) (rErr error) { 64 // if script exists, write it as a temporary file and execute it 65 if script != "" { 66 tmpFile, cleanup, err := Write(buildSpec, script) 67 if err != nil { 68 return err 69 } 70 defer func() { 71 if err := cleanup(); err != nil && rErr == nil { 72 rErr = errors.Wrapf(err, "failed to remove script file %s", tmpFile) 73 } 74 }() 75 76 currEnv := os.Environ() 77 distEnvVars := additionalEnvVars 78 env := make([]string, len(currEnv), len(currEnv)+len(distEnvVars)) 79 copy(env, currEnv) 80 for k, v := range distEnvVars { 81 env = append(env, fmt.Sprintf("%v=%v", k, v)) 82 } 83 84 cmd := exec.Command(tmpFile) 85 cmd.Env = env 86 cmd.Dir = buildSpec.ProjectDir 87 cmd.Stdout = stdOut 88 cmd.Stderr = stdErr 89 if err := cmd.Run(); err != nil { 90 return errors.Wrapf(err, "Dist script for %v failed", buildSpec.ProductName) 91 } 92 } 93 return nil 94 }