github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/gradle/gradle.go (about)

     1  package gradle
     2  
     3  import (
     4  	"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic"
     5  	commandsutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils"
     6  	"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
     7  	"github.com/jfrog/jfrog-cli-core/v2/common/build"
     8  	"github.com/jfrog/jfrog-cli-core/v2/common/format"
     9  	"github.com/jfrog/jfrog-cli-core/v2/common/project"
    10  	"github.com/jfrog/jfrog-cli-core/v2/utils/config"
    11  	gradleutils "github.com/jfrog/jfrog-cli-core/v2/utils/gradle"
    12  	"github.com/jfrog/jfrog-cli-core/v2/utils/ioutils"
    13  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    14  	"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
    15  	"github.com/spf13/viper"
    16  )
    17  
    18  type GradleCommand struct {
    19  	tasks              []string
    20  	configPath         string
    21  	configuration      *build.BuildConfiguration
    22  	serverDetails      *config.ServerDetails
    23  	threads            int
    24  	detailedSummary    bool
    25  	xrayScan           bool
    26  	scanOutputFormat   format.OutputFormat
    27  	result             *commandsutils.Result
    28  	deploymentDisabled bool
    29  	// File path for Gradle extractor in which all build's artifacts details will be listed at the end of the build.
    30  	buildArtifactsDetailsFile string
    31  }
    32  
    33  func NewGradleCommand() *GradleCommand {
    34  	return &GradleCommand{}
    35  }
    36  
    37  // Returns the ServerDetails. The information returns from the config file provided.
    38  func (gc *GradleCommand) ServerDetails() (*config.ServerDetails, error) {
    39  	// Get the serverDetails from the config file.
    40  	var err error
    41  	if gc.serverDetails == nil {
    42  		vConfig, err := project.ReadConfigFile(gc.configPath, project.YAML)
    43  		if err != nil {
    44  			return nil, err
    45  		}
    46  		gc.serverDetails, err = build.GetServerDetails(vConfig)
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  	}
    51  	return gc.serverDetails, err
    52  }
    53  
    54  func (gc *GradleCommand) SetServerDetails(serverDetails *config.ServerDetails) *GradleCommand {
    55  	gc.serverDetails = serverDetails
    56  	return gc
    57  }
    58  
    59  func (gc *GradleCommand) init() (vConfig *viper.Viper, err error) {
    60  	// Read config
    61  	vConfig, err = project.ReadConfigFile(gc.configPath, project.YAML)
    62  	if err != nil {
    63  		return
    64  	}
    65  	if gc.IsXrayScan() && !vConfig.IsSet("deployer") {
    66  		err = errorutils.CheckErrorf("Conditional upload can only be performed if deployer is set in the config")
    67  		return
    68  	}
    69  	// Gradle extractor is needed to run, in order to get the details of the build's artifacts.
    70  	// Gradle's extractor deploy build artifacts. This should be disabled since there is no intent to deploy anything or deploy upon Xray scan results.
    71  	gc.deploymentDisabled = gc.IsXrayScan() || !vConfig.IsSet("deployer")
    72  	if gc.shouldCreateBuildArtifactsFile() {
    73  		// Created a file that will contain all the details about the build's artifacts
    74  		tempFile, err := fileutils.CreateTempFile()
    75  		if err != nil {
    76  			return nil, err
    77  		}
    78  		// If this is a Windows machine there is a need to modify the path for the build info file to match Java syntax with double \\
    79  		gc.buildArtifactsDetailsFile = ioutils.DoubleWinPathSeparator(tempFile.Name())
    80  		if err = tempFile.Close(); errorutils.CheckError(err) != nil {
    81  			return nil, err
    82  		}
    83  	}
    84  	return
    85  }
    86  
    87  // Gradle extractor generates the details of the build's artifacts.
    88  // This is required for Xray scan and for the detailed summary.
    89  // We can either scan or print the generated artifacts.
    90  func (gc *GradleCommand) shouldCreateBuildArtifactsFile() bool {
    91  	return (gc.IsDetailedSummary() && !gc.deploymentDisabled) || gc.IsXrayScan()
    92  }
    93  
    94  func (gc *GradleCommand) Run() error {
    95  	vConfig, err := gc.init()
    96  	if err != nil {
    97  		return err
    98  	}
    99  	err = gradleutils.RunGradle(vConfig, gc.tasks, gc.buildArtifactsDetailsFile, gc.configuration, gc.threads, gc.IsXrayScan())
   100  	if err != nil {
   101  		return err
   102  	}
   103  	if gc.buildArtifactsDetailsFile != "" {
   104  		err = gc.unmarshalDeployableArtifacts(gc.buildArtifactsDetailsFile)
   105  		if err != nil {
   106  			return err
   107  		}
   108  		if gc.IsXrayScan() {
   109  			return gc.conditionalUpload()
   110  		}
   111  	}
   112  	return nil
   113  }
   114  
   115  func (gc *GradleCommand) unmarshalDeployableArtifacts(filesPath string) error {
   116  	result, err := commandsutils.UnmarshalDeployableArtifacts(filesPath, gc.configPath, gc.IsXrayScan())
   117  	if err != nil {
   118  		return err
   119  	}
   120  	gc.setResult(result)
   121  	return nil
   122  }
   123  
   124  // ConditionalUpload will scan the artifact using Xray and will upload them only if the scan passes with no
   125  // violation.
   126  func (gc *GradleCommand) conditionalUpload() error {
   127  	// Initialize the server details (from config) if it hasn't been initialized yet.
   128  	_, err := gc.ServerDetails()
   129  	if err != nil {
   130  		return err
   131  	}
   132  	binariesSpecFile, pomSpecFile, err := commandsutils.ScanDeployableArtifacts(gc.result, gc.serverDetails, gc.threads, gc.scanOutputFormat)
   133  	// If the detailed summary wasn't requested, the reader should be closed here.
   134  	// (otherwise it will be closed by the detailed summary print method)
   135  	if !gc.detailedSummary {
   136  		e := gc.result.Reader().Close()
   137  		if e != nil {
   138  			return e
   139  		}
   140  	} else {
   141  		gc.result.Reader().Reset()
   142  	}
   143  	if err != nil {
   144  		return err
   145  	}
   146  	// The case scan failed
   147  	if binariesSpecFile == nil {
   148  		return nil
   149  	}
   150  	// First upload binaries
   151  	if len(binariesSpecFile.Files) > 0 {
   152  		uploadCmd := generic.NewUploadCommand()
   153  		uploadConfiguration := new(utils.UploadConfiguration)
   154  		uploadConfiguration.Threads = gc.threads
   155  		uploadCmd.SetUploadConfiguration(uploadConfiguration).SetBuildConfiguration(gc.configuration).SetSpec(binariesSpecFile).SetServerDetails(gc.serverDetails)
   156  		err = uploadCmd.Run()
   157  		if err != nil {
   158  			return err
   159  		}
   160  	}
   161  	if len(pomSpecFile.Files) > 0 {
   162  		// Then Upload pom.xml's
   163  		uploadCmd := generic.NewUploadCommand()
   164  		uploadCmd.SetBuildConfiguration(gc.configuration).SetSpec(pomSpecFile).SetServerDetails(gc.serverDetails)
   165  		err = uploadCmd.Run()
   166  	}
   167  	return err
   168  }
   169  
   170  func (gc *GradleCommand) CommandName() string {
   171  	return "rt_gradle"
   172  }
   173  
   174  func (gc *GradleCommand) SetConfiguration(configuration *build.BuildConfiguration) *GradleCommand {
   175  	gc.configuration = configuration
   176  	return gc
   177  }
   178  
   179  func (gc *GradleCommand) SetConfigPath(configPath string) *GradleCommand {
   180  	gc.configPath = configPath
   181  	return gc
   182  }
   183  
   184  func (gc *GradleCommand) SetTasks(tasks []string) *GradleCommand {
   185  	gc.tasks = tasks
   186  	return gc
   187  }
   188  
   189  func (gc *GradleCommand) SetThreads(threads int) *GradleCommand {
   190  	gc.threads = threads
   191  	return gc
   192  }
   193  
   194  func (gc *GradleCommand) SetDetailedSummary(detailedSummary bool) *GradleCommand {
   195  	gc.detailedSummary = detailedSummary
   196  	return gc
   197  }
   198  
   199  func (gc *GradleCommand) IsDetailedSummary() bool {
   200  	return gc.detailedSummary
   201  }
   202  
   203  func (gc *GradleCommand) SetXrayScan(xrayScan bool) *GradleCommand {
   204  	gc.xrayScan = xrayScan
   205  	return gc
   206  }
   207  
   208  func (gc *GradleCommand) IsXrayScan() bool {
   209  	return gc.xrayScan
   210  }
   211  
   212  func (gc *GradleCommand) SetScanOutputFormat(format format.OutputFormat) *GradleCommand {
   213  	gc.scanOutputFormat = format
   214  	return gc
   215  }
   216  
   217  func (gc *GradleCommand) Result() *commandsutils.Result {
   218  	return gc.result
   219  }
   220  
   221  func (gc *GradleCommand) setResult(result *commandsutils.Result) *GradleCommand {
   222  	gc.result = result
   223  	return gc
   224  }