github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/gradle/gradle.go (about) 1 package gradle 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "io" 8 "os" 9 "path/filepath" 10 "strings" 11 12 "github.com/SAP/jenkins-library/pkg/log" 13 ) 14 15 const ( 16 gradleExecutable = "gradle" 17 gradlewExecutable = "./gradlew" 18 19 groovyBuildScriptName = "build.gradle" 20 kotlinBuildScriptName = "build.gradle.kts" 21 initScriptName = "initScript.gradle.tmp" 22 ) 23 24 type Utils interface { 25 Stdout(out io.Writer) 26 Stderr(err io.Writer) 27 RunExecutable(e string, p ...string) error 28 29 FileExists(filename string) (bool, error) 30 FileWrite(path string, content []byte, perm os.FileMode) error 31 FileRemove(path string) error 32 } 33 34 // ExecuteOptions are used by Execute() to construct the Gradle command line. 35 type ExecuteOptions struct { 36 BuildGradlePath string `json:"path,omitempty"` 37 Task string `json:"task,omitempty"` 38 BuildFlags []string `json:"buildFlags,omitempty"` 39 InitScriptContent string `json:"initScriptContent,omitempty"` 40 UseWrapper bool `json:"useWrapper,omitempty"` 41 ProjectProperties map[string]string `json:"projectProperties,omitempty"` 42 setInitScript bool 43 } 44 45 func Execute(options *ExecuteOptions, utils Utils) (string, error) { 46 stdOutBuf := new(bytes.Buffer) 47 utils.Stdout(io.MultiWriter(log.Writer(), stdOutBuf)) 48 utils.Stderr(log.Writer()) 49 50 _, err := searchBuildScript([]string{ 51 filepath.Join(options.BuildGradlePath, groovyBuildScriptName), 52 filepath.Join(options.BuildGradlePath, kotlinBuildScriptName), 53 }, utils.FileExists) 54 if err != nil { 55 return "", fmt.Errorf("the specified gradle build script could not be found: %v", err) 56 } 57 58 exec := gradleExecutable 59 if options.UseWrapper { 60 wrapperExists, err := utils.FileExists("gradlew") 61 if err != nil { 62 return "", err 63 } 64 if !wrapperExists { 65 return "", errors.New("gradle wrapper not found") 66 } 67 exec = gradlewExecutable 68 } 69 log.Entry().Infof("All commands will be executed with the '%s' tool", exec) 70 71 if options.InitScriptContent != "" { 72 parameters := []string{"tasks"} 73 if options.BuildGradlePath != "" { 74 parameters = append(parameters, "-p", options.BuildGradlePath) 75 } 76 if err := utils.RunExecutable(exec, parameters...); err != nil { 77 return "", fmt.Errorf("failed list gradle tasks: %v", err) 78 } 79 if !strings.Contains(stdOutBuf.String(), options.Task) { 80 err := utils.FileWrite(initScriptName, []byte(options.InitScriptContent), 0644) 81 if err != nil { 82 return "", fmt.Errorf("failed create init script: %v", err) 83 } 84 defer utils.FileRemove(initScriptName) 85 options.setInitScript = true 86 } 87 } 88 89 parameters := getParametersFromOptions(options) 90 91 err = utils.RunExecutable(exec, parameters...) 92 if err != nil { 93 log.SetErrorCategory(log.ErrorBuild) 94 commandLine := append([]string{exec}, parameters...) 95 return "", fmt.Errorf("failed to run executable, command: '%s', error: %v", commandLine, err) 96 } 97 98 return string(stdOutBuf.Bytes()), nil 99 } 100 101 func getParametersFromOptions(options *ExecuteOptions) []string { 102 var parameters []string 103 104 if len(options.BuildFlags) > 0 { 105 // respect the list of tasks/flags user wants to execute 106 parameters = append(parameters, options.BuildFlags...) 107 } else { 108 // default value for task is 'build', so no necessary to checking for empty parameter 109 parameters = append(parameters, options.Task) 110 } 111 112 // resolve path for build.gradle execution 113 if options.BuildGradlePath != "" { 114 parameters = append(parameters, "-p", options.BuildGradlePath) 115 } 116 117 for k, v := range options.ProjectProperties { 118 parameters = append(parameters, fmt.Sprintf("-P%s=%s", k, v)) 119 } 120 121 if options.setInitScript { 122 parameters = append(parameters, "--init-script", initScriptName) 123 } 124 125 return parameters 126 } 127 128 func searchBuildScript(supported []string, existsFunc func(string) (bool, error)) (string, error) { 129 var descriptor string 130 for _, f := range supported { 131 exists, err := existsFunc(f) 132 if err != nil { 133 return "", err 134 } 135 if exists { 136 descriptor = f 137 break 138 } 139 } 140 if len(descriptor) == 0 { 141 return "", fmt.Errorf("no build script available, supported: %v", supported) 142 } 143 return descriptor, nil 144 }