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

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