diff --git a/artifactory/commands/npm/artifactoryupload.go b/artifactory/commands/npm/artifactoryupload.go index 9fa760a7..6962d604 100644 --- a/artifactory/commands/npm/artifactoryupload.go +++ b/artifactory/commands/npm/artifactoryupload.go @@ -3,6 +3,7 @@ package npm import ( "errors" "fmt" + buildinfo "github.com/jfrog/build-info-go/entities" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -35,8 +36,8 @@ func (nru *npmRtUpload) upload() (err error) { return } -func (nru *npmRtUpload) getBuildArtifacts() ([]buildinfo.Artifact, error) { - return specutils.ConvertArtifactsDetailsToBuildInfoArtifacts(nru.artifactsDetailsReader) +func (nru *npmRtUpload) getBuildArtifacts() []buildinfo.Artifact { + return ConvertArtifactsDetailsToBuildInfoArtifacts(nru.artifactsDetailsReader, specutils.ConvertArtifactsDetailsToBuildInfoArtifacts) } func (nru *npmRtUpload) doDeploy(target string, artDetails *config.ServerDetails, packedFilePath string) error { @@ -63,7 +64,7 @@ func (nru *npmRtUpload) doDeploy(target string, artDetails *config.ServerDetails } totalFailed = summary.TotalFailed if nru.collectBuildInfo { - nru.artifactsDetailsReader = summary.ArtifactsDetailsReader + nru.artifactsDetailsReader = append(nru.artifactsDetailsReader, summary.ArtifactsDetailsReader) } else { err = summary.ArtifactsDetailsReader.Close() if err != nil { diff --git a/artifactory/commands/npm/npmpublish.go b/artifactory/commands/npm/npmpublish.go index 73f59969..6aec78f3 100644 --- a/artifactory/commands/npm/npmpublish.go +++ b/artifactory/commands/npm/npmpublish.go @@ -51,8 +51,8 @@ func (npu *npmPublish) upload() (err error) { return } -func (npu *npmPublish) getBuildArtifacts() ([]buildinfo.Artifact, error) { - return utils.ConvertArtifactsSearchDetailsToBuildInfoArtifacts(npu.artifactsDetailsReader) +func (npu *npmPublish) getBuildArtifacts() []buildinfo.Artifact { + return ConvertArtifactsDetailsToBuildInfoArtifacts(npu.artifactsDetailsReader, utils.ConvertArtifactsSearchDetailsToBuildInfoArtifacts) } func (npu *npmPublish) publishPackage(executablePath, filePath string, serverDetails *config.ServerDetails, target string) error { @@ -96,7 +96,7 @@ func (npu *npmPublish) publishPackage(executablePath, filePath string, serverDet if err != nil { log.Warn("Unable to set build properties: ", err, "\nThis may cause build to not properly link with artifact, please add build name and build number properties on the tarball artifact manually") } - npu.artifactsDetailsReader = searchReader + npu.artifactsDetailsReader = append(npu.artifactsDetailsReader, searchReader) } return nil } diff --git a/artifactory/commands/npm/publish.go b/artifactory/commands/npm/publish.go index 7b712293..601dd3da 100644 --- a/artifactory/commands/npm/publish.go +++ b/artifactory/commands/npm/publish.go @@ -44,7 +44,7 @@ type NpmPublishCommandArgs struct { packageInfo *biutils.PackageInfo publishPath string tarballProvided bool - artifactsDetailsReader *content.ContentReader + artifactsDetailsReader []*content.ContentReader xrayScan bool scanOutputFormat format.OutputFormat distTag string @@ -220,11 +220,10 @@ func (npc *NpmPublishCommand) Run() (err error) { npmModule.SetName(npc.buildConfiguration.GetModule()) } - buildArtifacts, err := publishStrategy.GetBuildArtifacts() - if err != nil { - return err + buildArtifacts := publishStrategy.GetBuildArtifacts() + for _, artifactReader := range npc.artifactsDetailsReader { + gofrogcmd.Close(artifactReader, &err) } - defer gofrogcmd.Close(npc.artifactsDetailsReader, &err) err = npmModule.AddArtifacts(buildArtifacts...) if err != nil { return errorutils.CheckError(err) diff --git a/artifactory/commands/npm/publishstrategy.go b/artifactory/commands/npm/publishstrategy.go index 9f02cb34..7789ac57 100644 --- a/artifactory/commands/npm/publishstrategy.go +++ b/artifactory/commands/npm/publishstrategy.go @@ -6,12 +6,13 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/common/format" "github.com/jfrog/jfrog-cli-core/v2/common/spec" "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-client-go/utils/io/content" "github.com/jfrog/jfrog-client-go/utils/log" ) type Publisher interface { upload() error - getBuildArtifacts() ([]buildinfo.Artifact, error) + getBuildArtifacts() []buildinfo.Artifact } type NpmPublishStrategy struct { @@ -37,11 +38,25 @@ func (nps *NpmPublishStrategy) Publish() error { return nps.strategy.upload() } -func (nps *NpmPublishStrategy) GetBuildArtifacts() ([]buildinfo.Artifact, error) { +func (nps *NpmPublishStrategy) GetBuildArtifacts() []buildinfo.Artifact { log.Debug("Using strategy for build info: ", nps.strategyName) return nps.strategy.getBuildArtifacts() } +// ConvertArtifactsDetailsToBuildInfoArtifacts converts artifact details readers to build info artifacts +// using the provided conversion function +func ConvertArtifactsDetailsToBuildInfoArtifacts(artifactsDetailsReader []*content.ContentReader, convertFunc func(*content.ContentReader) ([]buildinfo.Artifact, error)) []buildinfo.Artifact { + buildArtifacts := make([]buildinfo.Artifact, 0, len(artifactsDetailsReader)) + for _, artifactReader := range artifactsDetailsReader { + buildArtifact, err := convertFunc(artifactReader) + if err != nil { + log.Warn("Failed converting artifact details to build info artifacts: ", err.Error()) + } + buildArtifacts = append(buildArtifacts, buildArtifact...) + } + return buildArtifacts +} + func performXrayScan(filePath string, repo string, serverDetails *config.ServerDetails, scanOutputFormat format.OutputFormat) error { fileSpec := spec.NewBuilder(). Pattern(filePath). diff --git a/cliutils/flagkit/flags.go b/cliutils/flagkit/flags.go index 4a05b87d..f8381972 100644 --- a/cliutils/flagkit/flags.go +++ b/cliutils/flagkit/flags.go @@ -349,6 +349,7 @@ const ( npmPrefix = "npm-" npmDetailedSummary = npmPrefix + detailedSummary runNative = "run-native" + npmWorkspaces = "workspaces" // Unique nuget/dotnet config flags nugetV2 = "nuget-v2" @@ -676,7 +677,7 @@ var commandFlags = map[string][]string{ BuildName, BuildNumber, module, Project, runNative, }, NpmPublish: { - BuildName, BuildNumber, module, Project, npmDetailedSummary, xrayScan, xrOutput, runNative, + BuildName, BuildNumber, module, Project, npmDetailedSummary, xrayScan, xrOutput, runNative, npmWorkspaces, }, PnpmConfig: { global, serverIdResolve, repoResolve, @@ -817,7 +818,8 @@ var flagsMap = map[string]components.Flag{ bundle: components.NewStringFlag(bundle, "[Optional] If specified, only artifacts of the specified bundle are matched. The value format is bundle-name/bundle-version.", components.SetMandatoryFalse()), imageFile: components.NewStringFlag(imageFile, "[Mandatory] Path to a file which includes one line in the following format: @sha256:.", components.SetMandatoryTrue()), ocStartBuildRepo: components.NewStringFlag(repo, "[Mandatory] The name of the repository to which the image was pushed.", components.SetMandatoryTrue()), - runNative: components.NewBoolFlag(runNative, "[Default: false] Set to true if you'd like to use the native client configurations. Note: This flag would invoke native client behind the scenes, has performance implications and does not support deployment view and detailed summary.", components.WithBoolDefaultValueFalse()), + runNative: components.NewBoolFlag(runNative, "Set to true if you'd like to use the native client configurations. Note: This flag would invoke native client behind the scenes, has performance implications and does not support deployment view and detailed summary.", components.WithBoolDefaultValueFalse()), + npmWorkspaces: components.NewBoolFlag(npmWorkspaces, "Set to true if you'd like to use npm workspaces.", components.WithBoolDefaultValueFalse()), // Config specific commands flags interactive: components.NewBoolFlag(interactive, "[Default: true, unless $CI is true] Set to false if you do not want the config command to be interactive. If true, the --url option becomes optional.", components.WithBoolDefaultValueFalse()),