From efe29cb7a053a94d6a326b5bd5a6cba843e52ad5 Mon Sep 17 00:00:00 2001 From: dimanevelev Date: Thu, 28 Dec 2017 15:13:04 +0200 Subject: [PATCH] npm builds support --- jfrog-cli/artifactory/commands/npminstall.go | 62 ++++++++++++++------ jfrog-cli/artifactory/commands/npmpublish.go | 42 ++++++++----- jfrog-cli/artifactory/utils/npm/list.go | 12 ++-- jfrog-cli/artifactory/utils/utils.go | 28 +++++++++ 4 files changed, 102 insertions(+), 42 deletions(-) diff --git a/jfrog-cli/artifactory/commands/npminstall.go b/jfrog-cli/artifactory/commands/npminstall.go index da8768471..754de00c0 100644 --- a/jfrog-cli/artifactory/commands/npminstall.go +++ b/jfrog-cli/artifactory/commands/npminstall.go @@ -51,7 +51,7 @@ func NpmInstall(repo string, cliFlags *npm.CliFlags) (err error) { } if !npmi.collectBuildInfo { - log.Info("Npm install finished successfully.") + log.Info("npm install finished successfully.") return nil } @@ -67,7 +67,7 @@ func NpmInstall(repo string, cliFlags *npm.CliFlags) (err error) { return err } - log.Info("Npm install finished successfully.") + log.Info("npm install finished successfully.") return } @@ -81,21 +81,22 @@ func (npmi *npmInstall) preparePrerequisites(repo string) error { return err } - currentDir, err := os.Getwd() - if err != nil { - return errorutils.CheckError(err) + if err := npmi.setWorkingDirectory(); err != nil { + return err } - if currentDir, err = filepath.Abs(currentDir); err != nil { - return errorutils.CheckError(err) + if err := npmi.prepareArtifactoryPrerequisites(repo); err != nil { + return err } - npmi.workingDirectory = currentDir - log.Debug("Working directory set to:", npmi.workingDirectory) - if err = npmi.setArtifactoryAuth(); err != nil { - return errorutils.CheckError(err) + if err := npmi.prepareBuildInfo(); err != nil { + return err } + return npmi.backupProjectNpmrc() +} + +func (npmi *npmInstall) prepareArtifactoryPrerequisites(repo string) (err error) { npmAuth, artifactoryVersion, err := getArtifactoryDetails(npmi.artDetails) if err != nil { return err @@ -106,9 +107,19 @@ func (npmi *npmInstall) preparePrerequisites(repo string) error { return errorutils.CheckError(errors.New("This operation requires Artifactory version " + minSupportedArtifactoryVersion + " or higher.")) } + if err = utils.CheckIfRepoExists(repo, npmi.artDetails); err!= nil { + return err + } + + npmi.registry = getNpmRepositoryUrl(repo, npmi.artDetails.Url) + return nil +} + +func (npmi *npmInstall) prepareBuildInfo() error { + var err error if len(npmi.flags.BuildName) > 0 && len(npmi.flags.BuildNumber) > 0 { npmi.collectBuildInfo = true - if err := utils.SaveBuildGeneralDetails(npmi.flags.BuildName, npmi.flags.BuildNumber); err != nil { + if err = utils.SaveBuildGeneralDetails(npmi.flags.BuildName, npmi.flags.BuildNumber); err != nil { return err } @@ -116,9 +127,25 @@ func (npmi *npmInstall) preparePrerequisites(repo string) error { return err } } + return err +} - npmi.registry = getNpmRepositoryUrl(repo, npmi.artDetails.Url) - return npmi.backupProjectNpmrc() +func (npmi *npmInstall) setWorkingDirectory() error { + currentDir, err := os.Getwd() + if err != nil { + return errorutils.CheckError(err) + } + + if currentDir, err = filepath.Abs(currentDir); err != nil { + return errorutils.CheckError(err) + } + + npmi.workingDirectory = currentDir + log.Debug("Working directory set to:", npmi.workingDirectory) + if err = npmi.setArtifactoryAuth(); err != nil { + return errorutils.CheckError(err) + } + return nil } // In order to make sure the install downloads the dependencies from Artifactory, we are creating a.npmrc file in the project's root directory. @@ -221,7 +248,7 @@ func (npmi *npmInstall) collectDependenciesChecksums() error { return err } - producerConsumer := parallel.NewBounedRunner(3, false) + producerConsumer := parallel.NewBounedRunner(10, false) errorsQueue := serviceutils.NewErrorsQueue(1) handlerFunc := npmi.createGetDependencyInfoFunc(servicesManager) go func() { @@ -253,8 +280,7 @@ func (npmi *npmInstall) saveDependenciesData() error { } log.Warn(strings.Join(missingDependenciesText, "\n")) log.Warn("The npm dependencies above could not be found in Artifactory and therefore are not included in the build-info.\n" + - "You can fix this, by moving aside your project's node_modules and also your npm cache directories and then run this command again. " + - "This will force npm to download all dependencies from Artifactory. Future builds will not need to download these dependencies again.") + "Make sure the dependencies are available in Artifactory for this build.") } return nil } @@ -333,7 +359,7 @@ func (npmi *npmInstall) prepareDependencies(typeRestriction string) error { // Run npm list data, errData, err := npm.RunList(npmi.flags.NpmArgs+" -only="+typeRestriction, npmi.executablePath) if err != nil { - return err + log.Warn("npm list command failed with error:", err.Error()) } if len(errData) > 0 { log.Warn("Some errors occurred while collecting dependencies info:\n" + string(errData)) diff --git a/jfrog-cli/artifactory/commands/npmpublish.go b/jfrog-cli/artifactory/commands/npmpublish.go index 014e49337..67d09b3df 100644 --- a/jfrog-cli/artifactory/commands/npmpublish.go +++ b/jfrog-cli/artifactory/commands/npmpublish.go @@ -16,18 +16,18 @@ import ( "io" "compress/gzip" "io/ioutil" - "github.com/jfrogdev/jfrog-cli-go/jfrog-client/utils" + clientutils"github.com/jfrogdev/jfrog-cli-go/jfrog-client/utils" "github.com/jfrogdev/jfrog-cli-go/jfrog-client/artifactory/services" specutils "github.com/jfrogdev/jfrog-cli-go/jfrog-client/artifactory/services/utils" - buildUtils "github.com/jfrogdev/jfrog-cli-go/jfrog-cli/artifactory/utils" + "github.com/jfrogdev/jfrog-cli-go/jfrog-cli/artifactory/utils" "time" "strconv" "github.com/jfrogdev/jfrog-cli-go/jfrog-cli/artifactory/utils/buildinfo" ) func NpmPublish(repo string, cliFlags *npm.CliFlags) (err error) { - log.Info("Running Npm Publish") - npmp := npmPublish{cliFlags: cliFlags} + log.Info("Running npm Publish") + npmp := npmPublish{cliFlags: cliFlags, repo: repo} if err = npmp.preparePrerequisites(); err != nil { return err } @@ -38,7 +38,7 @@ func NpmPublish(repo string, cliFlags *npm.CliFlags) (err error) { } } - if err = npmp.deploy(repo, cliFlags.ArtDetails); err != nil { + if err = npmp.deploy(); err != nil { if npmp.tarballProvided { return err } @@ -53,7 +53,7 @@ func NpmPublish(repo string, cliFlags *npm.CliFlags) (err error) { } if !npmp.collectBuildInfo { - log.Info("Npm publish finished successfully.") + log.Info("npm publish finished successfully.") return nil } @@ -61,7 +61,7 @@ func NpmPublish(repo string, cliFlags *npm.CliFlags) (err error) { return err } - log.Info("Npm publish finished successfully.") + log.Info("npm publish finished successfully.") return nil } @@ -95,6 +95,15 @@ func (npmp *npmPublish) preparePrerequisites() error { return err } + artDetails, err := npmp.cliFlags.ArtDetails.CreateArtAuthConfig() + if err != nil { + return err + } + + if err = utils.CheckIfRepoExists(npmp.repo, artDetails); err != nil { + return err + } + return npmp.setPackageInfo() } @@ -109,14 +118,14 @@ func (npmp *npmPublish) pack() error { return nil } -func (npmp *npmPublish) deploy(repo string, artDetails *config.ArtifactoryDetails) (err error) { +func (npmp *npmPublish) deploy() (err error) { log.Debug("Deploying npm package.") if err = npmp.readPackageInfoFromTarball(); err != nil { return err } - target := fmt.Sprintf("%s/%s", repo, npmp.packageInfo.GetDeployPath()) - artifactsFileInfo, err := npmp.doDeploy(target, artDetails) + target := fmt.Sprintf("%s/%s", npmp.repo, npmp.packageInfo.GetDeployPath()) + artifactsFileInfo, err := npmp.doDeploy(target, npmp.cliFlags.ArtDetails) if err != nil { return err } @@ -126,7 +135,7 @@ func (npmp *npmPublish) deploy(repo string, artDetails *config.ArtifactoryDetail } func (npmp *npmPublish) doDeploy(target string, artDetails *config.ArtifactoryDetails) (artifactsFileInfo []specutils.FileInfo, err error) { - servicesManager, err := buildUtils.CreateServiceManager(artDetails, false) + servicesManager, err := utils.CreateServiceManager(artDetails, false) if err != nil { return nil, err } @@ -148,14 +157,14 @@ func (npmp *npmPublish) doDeploy(target string, artDetails *config.ArtifactoryDe // We deploying only one Artifact which have to be deployed, in case of failure we should fail if failed > 0 { - return nil, errorutils.CheckError(errors.New("Failed to upload the npm package to Artifactory. Please see Artifactory logs for more details.")) + return nil, errorutils.CheckError(errors.New("Failed to upload the npm package to Artifactory. See Artifactory logs for more details.")) } return artifactsFileInfo, nil } func getBuildTimestamp(buildName, buildNumber string) (timestamp string, err error) { - buildUtils.SaveBuildGeneralDetails(buildName, buildNumber) - buildDetails, err := buildUtils.ReadBuildInfoGeneralDetails(buildName, buildNumber) + utils.SaveBuildGeneralDetails(buildName, buildNumber) + buildDetails, err := utils.ReadBuildInfoGeneralDetails(buildName, buildNumber) if err != nil { return "", err } @@ -169,7 +178,7 @@ func (npmp *npmPublish) saveArtifactData() error { partial.Artifacts = buildArtifacts partial.ModuleId = npmp.packageInfo.BuildInfoModuleId() } - return buildUtils.SavePartialBuildInfo(npmp.cliFlags.BuildName, npmp.cliFlags.BuildNumber, populateFunc) + return utils.SavePartialBuildInfo(npmp.cliFlags.BuildName, npmp.cliFlags.BuildNumber, populateFunc) } func (npmp *npmPublish) setPublishPath() error { @@ -182,7 +191,7 @@ func (npmp *npmPublish) setPublishPath() error { npmp.publishPath = npmp.workingDirectory if len(splitFlags) > 0 && !strings.HasPrefix(strings.TrimSpace(splitFlags[0]), "-") { path := strings.TrimSpace(splitFlags[0]) - path = utils.ReplaceTildeWithUserHome(path) + path = clientutils.ReplaceTildeWithUserHome(path) if err != nil { return errorutils.CheckError(err) } @@ -272,4 +281,5 @@ type npmPublish struct { publishPath string tarballProvided bool artifactData []specutils.FileInfo + repo string } diff --git a/jfrog-cli/artifactory/utils/npm/list.go b/jfrog-cli/artifactory/utils/npm/list.go index 53f79d9a7..3d5ef59eb 100644 --- a/jfrog-cli/artifactory/utils/npm/list.go +++ b/jfrog-cli/artifactory/utils/npm/list.go @@ -19,13 +19,9 @@ func RunList(flags, executablePath string) (stdResult, errResult []byte, err err listCmd := createListCommand(executablePath, splitFlags) outData, errData, err := listCmd.exec() - if err != nil { - return nil, nil, err - } - - log.Debug("npm list standard output is: \n" + string(outData)) - log.Debug("npm list error output is: \n" + string(errData)) - return outData, errData, nil + log.Debug("npm list standard output is:\n" + string(outData)) + log.Debug("npm list error output is:\n" + string(errData)) + return outData, errData, err } func (listCmd *listCommand) exec() (outData, errData []byte, err error) { @@ -56,7 +52,7 @@ func (listCmd *listCommand) exec() (outData, errData []byte, err error) { wg.Wait() for _, err := range cmdErrors { if err != nil { - return nil, nil, errorutils.CheckError(err) + return outData, errData, errorutils.CheckError(err) } } return outData, errData, nil diff --git a/jfrog-cli/artifactory/utils/utils.go b/jfrog-cli/artifactory/utils/utils.go index dfd52b1d7..5eb02b708 100644 --- a/jfrog-cli/artifactory/utils/utils.go +++ b/jfrog-cli/artifactory/utils/utils.go @@ -18,8 +18,11 @@ import ( "path/filepath" "io" "github.com/jfrogdev/jfrog-cli-go/jfrog-client/utils/log" + "github.com/jfrogdev/jfrog-cli-go/jfrog-client/utils/io/httputils" ) +const repoDetailsUrl = "api/repositories/" + func GetJfrogSecurityDir() (string, error) { homeDir, err := config.GetJfrogHomeDir() if err != nil { @@ -88,6 +91,31 @@ func ConvertResultItemArrayToDeleteItemArray(resultItems []clientutils.ResultIte return deleteItems } +func isRepoExists(repository string, artDetails *auth.ArtifactoryDetails) (bool, error) { + artHttpDetails := artDetails.CreateArtifactoryHttpClientDetails() + resp, _, _, err := httputils.SendGet(artDetails.Url+repoDetailsUrl+repository, true, artHttpDetails) + if err != nil { + return false, errorutils.CheckError(err) + } + + if resp.StatusCode != http.StatusBadRequest { + return true, nil + } + return false, nil +} + +func CheckIfRepoExists(repository string, artDetails *auth.ArtifactoryDetails) error { + repoExists, err := isRepoExists(repository, artDetails) + if err != nil { + return err + } + + if !repoExists { + return errorutils.CheckError(errors.New("The repository '" + repository + "' dose not exists.")) + } + return nil +} + func RunCmd(config CmdConfig) error { for k, v := range config.GetEnv() { os.Setenv(k, v)