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

     1  package utils
     2  
     3  import (
     4  	"encoding/json"
     5  	ioutils "github.com/jfrog/gofrog/io"
     6  	"io"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/jfrog/build-info-go/entities"
    11  	"github.com/jfrog/jfrog-cli-core/v2/common/build"
    12  	"github.com/jfrog/jfrog-cli-core/v2/common/format"
    13  	"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
    14  	"github.com/jfrog/jfrog-client-go/artifactory"
    15  	"github.com/jfrog/jfrog-client-go/artifactory/services"
    16  	servicesUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils"
    17  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    18  	"github.com/jfrog/jfrog-client-go/utils/log"
    19  )
    20  
    21  type aqlResult struct {
    22  	Results []*servicesUtils.ResultItem `json:"results,omitempty"`
    23  }
    24  
    25  func GetDependenciesFromLatestBuild(servicesManager artifactory.ArtifactoryServicesManager, buildName string) (map[string]*entities.Dependency, error) {
    26  	buildDependencies := make(map[string]*entities.Dependency)
    27  	previousBuild, found, err := servicesManager.GetBuildInfo(services.BuildInfoParams{BuildName: buildName, BuildNumber: servicesUtils.LatestBuildNumberKey})
    28  	if err != nil || !found {
    29  		return buildDependencies, err
    30  	}
    31  	for _, module := range previousBuild.BuildInfo.Modules {
    32  		for _, dependency := range module.Dependencies {
    33  			buildDependencies[dependency.Id] = &entities.Dependency{Id: dependency.Id, Type: dependency.Type,
    34  				Checksum: entities.Checksum{Md5: dependency.Md5, Sha1: dependency.Sha1}}
    35  		}
    36  	}
    37  	return buildDependencies, nil
    38  }
    39  
    40  // Get dependency's checksum and type.
    41  func getDependencyInfo(name, ver string, previousBuildDependencies map[string]*entities.Dependency,
    42  	servicesManager artifactory.ArtifactoryServicesManager) (checksum entities.Checksum, fileType string, err error) {
    43  	id := name + ":" + ver
    44  	if dep, ok := previousBuildDependencies[id]; ok {
    45  		// Get checksum from previous build.
    46  		checksum = dep.Checksum
    47  		fileType = dep.Type
    48  		return
    49  	}
    50  
    51  	// Get info from Artifactory.
    52  	log.Debug("Fetching checksums for", id)
    53  	var stream io.ReadCloser
    54  	stream, err = servicesManager.Aql(servicesUtils.CreateAqlQueryForYarn(name, ver))
    55  	if err != nil {
    56  		return
    57  	}
    58  	defer ioutils.Close(stream, &err)
    59  	var result []byte
    60  	result, err = io.ReadAll(stream)
    61  	if err != nil {
    62  		return
    63  	}
    64  	parsedResult := new(aqlResult)
    65  	if err = json.Unmarshal(result, parsedResult); err != nil {
    66  		return entities.Checksum{}, "", errorutils.CheckError(err)
    67  	}
    68  	if len(parsedResult.Results) == 0 {
    69  		log.Debug(id, "could not be found in Artifactory.")
    70  		return
    71  	}
    72  	if i := strings.LastIndex(parsedResult.Results[0].Name, "."); i != -1 {
    73  		fileType = parsedResult.Results[0].Name[i+1:]
    74  	}
    75  	log.Debug(id, "was found in Artifactory. Name:", parsedResult.Results[0].Name,
    76  		"SHA-1:", parsedResult.Results[0].Actual_Sha1,
    77  		"MD5:", parsedResult.Results[0].Actual_Md5)
    78  
    79  	checksum = entities.Checksum{Sha1: parsedResult.Results[0].Actual_Sha1, Md5: parsedResult.Results[0].Actual_Md5, Sha256: parsedResult.Results[0].Sha256}
    80  	return
    81  }
    82  
    83  func ExtractYarnOptionsFromArgs(args []string) (threads int, detailedSummary, xrayScan bool, scanOutputFormat format.OutputFormat, cleanArgs []string, buildConfig *build.BuildConfiguration, err error) {
    84  	threads = 3
    85  	// Extract threads information from the args.
    86  	flagIndex, valueIndex, numOfThreads, err := coreutils.FindFlag("--threads", args)
    87  	if err != nil {
    88  		return
    89  	}
    90  	coreutils.RemoveFlagFromCommand(&args, flagIndex, valueIndex)
    91  	if numOfThreads != "" {
    92  		threads, err = strconv.Atoi(numOfThreads)
    93  		if err != nil {
    94  			err = errorutils.CheckError(err)
    95  			return
    96  		}
    97  	}
    98  	detailedSummary, xrayScan, scanOutputFormat, cleanArgs, buildConfig, err = ExtractNpmOptionsFromArgs(args)
    99  	return
   100  }
   101  
   102  func PrintMissingDependencies(missingDependencies []string) {
   103  	if len(missingDependencies) == 0 {
   104  		return
   105  	}
   106  
   107  	log.Warn(strings.Join(missingDependencies, "\n"), "\nThe npm dependencies above could not be found in Artifactory and therefore are not included in the build-info.\n"+
   108  		"Deleting the local cache will force populating Artifactory with these dependencies.")
   109  }
   110  
   111  func CreateCollectChecksumsFunc(previousBuildDependencies map[string]*entities.Dependency, servicesManager artifactory.ArtifactoryServicesManager, missingDepsChan chan string) func(dependency *entities.Dependency) (bool, error) {
   112  	return func(dependency *entities.Dependency) (bool, error) {
   113  		splitDepId := strings.SplitN(dependency.Id, ":", 2)
   114  		name := splitDepId[0]
   115  		ver := splitDepId[1]
   116  
   117  		// Get dependency info.
   118  		checksum, fileType, err := getDependencyInfo(name, ver, previousBuildDependencies, servicesManager)
   119  		if err != nil || checksum.IsEmpty() {
   120  			missingDepsChan <- dependency.Id
   121  			return false, err
   122  		}
   123  
   124  		// Update dependency.
   125  		dependency.Type = fileType
   126  		dependency.Checksum = checksum
   127  		return true, nil
   128  	}
   129  }