Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish multiple npm workspaces packages #1149

Merged
merged 12 commits into from
Mar 12, 2024
104 changes: 64 additions & 40 deletions artifactory/commands/npm/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package npm
import (
"archive/tar"
"compress/gzip"
"errors"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -37,7 +38,7 @@ type NpmPublishCommandArgs struct {
executablePath string
workingDirectory string
collectBuildInfo bool
packedFilePath string
packedFilesPath []string
EyalDelarea marked this conversation as resolved.
Show resolved Hide resolved
packageInfo *biutils.PackageInfo
publishPath string
tarballProvided bool
Expand Down Expand Up @@ -172,11 +173,11 @@ func (npc *NpmPublishCommand) Run() (err error) {
return err
}
// We should delete the tarball we created
return deleteCreatedTarballAndError(npc.packedFilePath, err)
return deleteCreatedTarballAndError(npc.packedFilesPath, err)
}

if !npc.tarballProvided {
if err := deleteCreatedTarball(npc.packedFilePath); err != nil {
if err := deleteCreatedTarball(npc.packedFilesPath); err != nil {
return err
}
}
Expand Down Expand Up @@ -217,6 +218,7 @@ func (npc *NpmPublishCommand) CommandName() string {
}

func (npc *NpmPublishCommand) preparePrerequisites() error {
npc.packedFilesPath = make([]string, 0)
currentDir, err := os.Getwd()
if err != nil {
return errorutils.CheckError(err)
Expand Down Expand Up @@ -251,7 +253,7 @@ func (npc *NpmPublishCommand) preparePrerequisites() error {

func (npc *NpmPublishCommand) pack() error {
log.Debug("Creating npm package.")
packageFileName, err := npm.Pack(npc.npmArgs, npc.executablePath)
packedFileNames, err := npm.Pack(npc.npmArgs, npc.executablePath)
if err != nil {
return err
}
Expand All @@ -261,8 +263,11 @@ func (npc *NpmPublishCommand) pack() error {
return err
}

npc.packedFilePath = filepath.Join(tarballDir, packageFileName)
log.Debug("Created npm package at", npc.packedFilePath)
for index, packageFileName := range packedFileNames {
npc.packedFilesPath = append(npc.packedFilesPath, filepath.Join(tarballDir, packageFileName))
log.Debug("Created npm package at", npc.packedFilesPath[index])
}
EyalDelarea marked this conversation as resolved.
Show resolved Hide resolved

return nil
}

Expand All @@ -279,34 +284,36 @@ func (npc *NpmPublishCommand) getTarballDir() (string, error) {
return dest, nil
}

func (npc *NpmPublishCommand) publish() error {
log.Debug("Deploying npm package.")
if err := npc.readPackageInfoFromTarball(); err != nil {
return err
}
target := fmt.Sprintf("%s/%s", npc.repo, npc.packageInfo.GetDeployPath())

// If requested, perform a Xray binary scan before deployment. If a FailBuildError is returned, skip the deployment.
if npc.xrayScan {
fileSpec := spec.NewBuilder().
Pattern(npc.packedFilePath).
Target(npc.repo + "/").
BuildSpec()
err := commandsutils.ConditionalUploadScanFunc(npc.serverDetails, fileSpec, 1, npc.scanOutputFormat)
if err != nil {
return err
func (npc *NpmPublishCommand) publish() (err error) {
for _, packedFilePath := range npc.packedFilesPath {
log.Debug("Deploying npm package.")
if err = npc.readPackageInfoFromTarball(packedFilePath); err != nil {
return
}
target := fmt.Sprintf("%s/%s", npc.repo, npc.packageInfo.GetDeployPath())

// If requested, perform a Xray binary scan before deployment. If a FailBuildError is returned, skip the deployment.
if npc.xrayScan {
fileSpec := spec.NewBuilder().
Pattern(packedFilePath).
Target(npc.repo + "/").
BuildSpec()
if err = commandsutils.ConditionalUploadScanFunc(npc.serverDetails, fileSpec, 1, npc.scanOutputFormat); err != nil {
return
}
}
err = errors.Join(err, npc.doDeploy(target, npc.serverDetails, packedFilePath))
}
return npc.doDeploy(target, npc.serverDetails)
return
}

func (npc *NpmPublishCommand) doDeploy(target string, artDetails *config.ServerDetails) error {
func (npc *NpmPublishCommand) doDeploy(target string, artDetails *config.ServerDetails, packedFilePath string) error {
servicesManager, err := utils.CreateServiceManager(artDetails, -1, 0, false)
if err != nil {
return err
}
up := services.NewUploadParams()
up.CommonParams = &specutils.CommonParams{Pattern: npc.packedFilePath, Target: target}
up.CommonParams = &specutils.CommonParams{Pattern: packedFilePath, Target: target}
var totalFailed int
if npc.collectBuildInfo || npc.detailedSummary {
if npc.collectBuildInfo {
Expand Down Expand Up @@ -341,9 +348,15 @@ func (npc *NpmPublishCommand) doDeploy(target string, artDetails *config.ServerD
}
}
if npc.detailedSummary {
npc.result.SetReader(summary.TransferDetailsReader)
npc.result.SetFailCount(totalFailed)
npc.result.SetSuccessCount(summary.TotalSucceeded)
npc.result.SetFailCount(npc.result.FailCount() + totalFailed)
npc.result.SetSuccessCount(npc.result.SuccessCount() + summary.TotalSucceeded)
if npc.result.Reader() == nil {
npc.result.SetReader(summary.TransferDetailsReader)
} else {
if err = npc.appendReader(summary); err != nil {
return err
}
}
EyalDelarea marked this conversation as resolved.
Show resolved Hide resolved
} else {
err = summary.TransferDetailsReader.Close()
if err != nil {
Expand All @@ -364,6 +377,16 @@ func (npc *NpmPublishCommand) doDeploy(target string, artDetails *config.ServerD
return nil
}

func (npc *NpmPublishCommand) appendReader(summary *specutils.OperationSummary) error {
readersSlice := []*content.ContentReader{npc.result.Reader(), summary.TransferDetailsReader}
reader, err := content.MergeReaders(readersSlice, content.DefaultKey)
if err != nil {
return err
}
npc.result.SetReader(reader)
return nil
}

func (npc *NpmPublishCommand) setPublishPath() error {
log.Debug("Reading Package Json.")

Expand Down Expand Up @@ -394,13 +417,12 @@ func (npc *NpmPublishCommand) setPackageInfo() error {
}
log.Debug("The provided path is not a directory, we assume this is a compressed npm package")
npc.tarballProvided = true
npc.packedFilePath = npc.publishPath
return npc.readPackageInfoFromTarball()
return npc.readPackageInfoFromTarball(npc.publishPath)
}

func (npc *NpmPublishCommand) readPackageInfoFromTarball() (err error) {
log.Debug("Extracting info from npm package:", npc.packedFilePath)
tarball, err := os.Open(npc.packedFilePath)
func (npc *NpmPublishCommand) readPackageInfoFromTarball(packedFilePath string) (err error) {
log.Debug("Extracting info from npm package:", npc.packedFilesPath)
tarball, err := os.Open(packedFilePath)
if err != nil {
return errorutils.CheckError(err)
}
Expand All @@ -420,7 +442,7 @@ func (npc *NpmPublishCommand) readPackageInfoFromTarball() (err error) {
hdr, err := tarReader.Next()
if err != nil {
if err == io.EOF {
return errorutils.CheckErrorf("Could not find 'package.json' in the compressed npm package: " + npc.packedFilePath)
return errorutils.CheckErrorf("Could not find 'package.json' in the compressed npm package: " + packedFilePath)
}
return errorutils.CheckError(err)
}
Expand All @@ -436,18 +458,20 @@ func (npc *NpmPublishCommand) readPackageInfoFromTarball() (err error) {
}
}

func deleteCreatedTarballAndError(packedFilePath string, currentError error) error {
if err := deleteCreatedTarball(packedFilePath); err != nil {
func deleteCreatedTarballAndError(packedFilesPath []string, currentError error) error {
if err := deleteCreatedTarball(packedFilesPath); err != nil {
EyalDelarea marked this conversation as resolved.
Show resolved Hide resolved
errorText := fmt.Sprintf("Two errors occurred: \n%s \n%s", currentError, err)
return errorutils.CheckErrorf(errorText)
}
return currentError
}

func deleteCreatedTarball(packedFilePath string) error {
if err := os.Remove(packedFilePath); err != nil {
return errorutils.CheckError(err)
func deleteCreatedTarball(packedFilesPath []string) error {
for _, packedFilePath := range packedFilesPath {
if err := os.Remove(packedFilePath); err != nil {
return errorutils.CheckError(err)
}
log.Debug("Successfully deleted the created npm package:", packedFilePath)
}
log.Debug("Successfully deleted the created npm package:", packedFilePath)
return nil
}
13 changes: 10 additions & 3 deletions artifactory/commands/npm/publish_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ import (

func TestReadPackageInfoFromTarball(t *testing.T) {
npmPublish := NewNpmPublishCommand()
npmPublish.packedFilePath = filepath.Join("..", "testdata", "npm", "npm-example-0.0.3.tgz")
err := npmPublish.readPackageInfoFromTarball()
assert.NoError(t, err)
npmPublish.packedFilesPath = append(npmPublish.packedFilesPath, filepath.Join("..", "testdata", "npm", "npm-example-0.0.3.tgz"))
npmPublish.packedFilesPath = append(npmPublish.packedFilesPath, filepath.Join("..", "testdata", "npm", "npm-example-0.0.4.tgz"))

err := npmPublish.readPackageInfoFromTarball(npmPublish.packedFilesPath[0])
assert.NoError(t, err)
assert.Equal(t, "npm-example", npmPublish.packageInfo.Name)
assert.Equal(t, "0.0.3", npmPublish.packageInfo.Version)

err = npmPublish.readPackageInfoFromTarball(npmPublish.packedFilesPath[1])
assert.NoError(t, err)
assert.Equal(t, "npm-example", npmPublish.packageInfo.Name)
assert.Equal(t, "0.0.4", npmPublish.packageInfo.Version)

}
Binary file not shown.
11 changes: 5 additions & 6 deletions artifactory/utils/npm/pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"github.com/jfrog/jfrog-client-go/utils/errorutils"
)

func Pack(npmFlags []string, executablePath string) (string, error) {
func Pack(npmFlags []string, executablePath string) ([]string, error) {
configListCmdConfig := createPackCmdConfig(executablePath, npmFlags)
output, err := gofrogcmd.RunCmdOutput(configListCmdConfig)
if err != nil {
return "", errorutils.CheckError(err)
return []string{}, errorutils.CheckError(err)
}
return getPackageFileNameFromOutput(output)
return getPackageFileNameFromOutput(output), nil
}

func createPackCmdConfig(executablePath string, splitFlags []string) *npmutils.NpmConfig {
Expand All @@ -27,8 +27,7 @@ func createPackCmdConfig(executablePath string, splitFlags []string) *npmutils.N
}
}

func getPackageFileNameFromOutput(output string) (string, error) {
func getPackageFileNameFromOutput(output string) []string {
output = strings.TrimSpace(output)
lines := strings.Split(output, "\n")
return strings.TrimSpace(lines[len(lines)-1]), nil
return strings.Split(output, "\n")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will work on windows?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like from the CLI test that it is working on windows 👍

}
6 changes: 1 addition & 5 deletions artifactory/utils/npm/pack_test.go
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed this test as the test case was irrelevant.
We checked the whole output of the CMD and tried to extract the tar.gz file name, as in practice, the npm cmd already gives us the name. and all we have to do now is to split the file names if we have more then one.
I've deleted the test here, and added a full test in CLI side to publish multiple packages.

Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ func TestGetPackageFileNameFromOutput(t *testing.T) {
assert.NoError(t, err)
return
}
actualFilename, err := getPackageFileNameFromOutput(string(output))
if err != nil {
assert.NoError(t, err)
return
}
actualFilename := getPackageFileNameFromOutput(string(output))
assert.Equal(t, test.expectedPackageFilename, actualFilename)
})
}
Expand Down
Loading