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  }