Skip to content

Commit

Permalink
Support running npm install without package.json
Browse files Browse the repository at this point in the history
  • Loading branch information
yahavi committed Oct 18, 2023
1 parent 8eb64e7 commit 4747a71
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 39 deletions.
2 changes: 1 addition & 1 deletion build/npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func newNpmModule(srcPath string, containingBuild *Build) (*NpmModule, error) {
}

// Read module name
packageInfo, err := buildutils.ReadPackageInfoFromPackageJson(srcPath, npmVersion)
packageInfo, err := buildutils.ReadPackageInfoFromPackageJsonIfExist(srcPath, npmVersion)
if err != nil {
return nil, err
}
Expand Down
10 changes: 8 additions & 2 deletions build/utils/npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,16 @@ type PackageInfo struct {
Scope string
}

func ReadPackageInfoFromPackageJson(packageJsonDirectory string, npmVersion *version.Version) (*PackageInfo, error) {
// Read and populate package name, version and scope from the package.json file in the provided directory.
// If package.json does not exist, return an empty PackageInfo object.
func ReadPackageInfoFromPackageJsonIfExist(packageJsonDirectory string, npmVersion *version.Version) (*PackageInfo, error) {
packageJson, err := os.ReadFile(filepath.Join(packageJsonDirectory, "package.json"))
if err != nil {
return nil, err
if os.IsNotExist(err) {
return &PackageInfo{}, nil
} else {
return nil, err
}
}
return ReadPackageInfo(packageJson, npmVersion)
}
Expand Down
83 changes: 50 additions & 33 deletions build/utils/npm_test.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
package utils

import (
"github.com/jfrog/build-info-go/entities"
"github.com/stretchr/testify/require"
"os"
"path/filepath"
"reflect"
"strings"
"testing"
"time"

"github.com/jfrog/build-info-go/entities"
"github.com/stretchr/testify/require"

testdatautils "github.com/jfrog/build-info-go/build/testdata"
"github.com/jfrog/build-info-go/utils"
"github.com/stretchr/testify/assert"
)

var logger = utils.NewDefaultLogger(utils.INFO)

func TestReadPackageInfoFromPackageJson(t *testing.T) {
func TestReadPackageInfo(t *testing.T) {
npmVersion, _, err := GetNpmVersionAndExecPath(logger)
if err != nil {
assert.NoError(t, err)
Expand All @@ -31,18 +32,48 @@ func TestReadPackageInfoFromPackageJson(t *testing.T) {
&PackageInfo{Name: "build-info-go-tests", Version: "1.0.0", Scope: ""}},
{`{ "name": "@jfrog/build-info-go-tests", "version": "1.0.0", "description": "test package"}`,
&PackageInfo{Name: "build-info-go-tests", Version: "1.0.0", Scope: "@jfrog"}},
{`{}`, &PackageInfo{}},
}
for _, test := range tests {
t.Run(test.json, func(t *testing.T) {
packInfo, err := ReadPackageInfo([]byte(test.json), npmVersion)
if err != nil {
t.Error("No error was expected in this test", err)
}
assert.NoError(t, err)
assert.Equal(t, test.pi, packInfo)
})
}
}

func TestReadPackageInfoFromPackageJsonIfExist(t *testing.T) {
// Prepare tests
npmVersion, _, err := GetNpmVersionAndExecPath(logger)
assert.NoError(t, err)
path, err := filepath.Abs(filepath.Join("..", "testdata"))
assert.NoError(t, err)
projectPath, cleanup := testdatautils.CreateNpmTest(t, path, "project1", false, npmVersion)
defer cleanup()

equals := reflect.DeepEqual(test.pi, packInfo)
if !equals {
t.Error("expected:", test.pi, "got:", packInfo)
testCases := []struct {
testName string
packageJsonDirectory string
expectedPackageInfo *PackageInfo
}{
{"Happy flow", projectPath, &PackageInfo{Name: "build-info-go-tests", Version: "1.0.0"}},
{"No package.json in path", path, &PackageInfo{Name: "", Version: ""}},
{"Path to file", filepath.Join(projectPath, "package.json"), nil},
}

for _, testCase := range testCases {
t.Run(testCase.testName, func(t *testing.T) {
packageInfo, err := ReadPackageInfoFromPackageJsonIfExist(testCase.packageJsonDirectory, npmVersion)
if testCase.expectedPackageInfo == nil {
assert.Error(t, err)
return
}
assert.NoError(t, err)
removeVersionPrefixes(packageInfo)
assert.Equal(t, testCase.expectedPackageInfo.Name, packageInfo.Name)
actualVersion, _ := strings.CutPrefix(packageInfo.Version, "v")
assert.Equal(t, testCase.expectedPackageInfo.Version, actualVersion)
})
}
}
Expand All @@ -57,10 +88,7 @@ func TestGetDeployPath(t *testing.T) {
}
for _, test := range tests {
t.Run(test.expectedPath, func(t *testing.T) {
actualPath := test.pi.GetDeployPath()
if actualPath != test.expectedPath {
t.Error("expected:", test.expectedPath, "got:", actualPath)
}
assert.Equal(t, test.expectedPath, test.pi.GetDeployPath())
})
}
}
Expand Down Expand Up @@ -93,15 +121,8 @@ func TestParseDependencies(t *testing.T) {
}
dependencies := make(map[string]*dependencyInfo)
err = parseDependencies(dependenciesJsonList, []string{"root"}, dependencies, npmLsDependencyParser, utils.NewDefaultLogger(utils.INFO))
if err != nil {
t.Error(err)
}
if len(expectedDependenciesList) != len(dependencies) {
t.Error("The expected dependencies list length is", len(expectedDependenciesList), "and should be:\n", expectedDependenciesList,
"\nthe actual dependencies list length is", len(dependencies), "and the list is:\n", dependencies)
t.Error("The expected dependencies list length is", len(expectedDependenciesList), "and should be:\n", expectedDependenciesList,
"\nthe actual dependencies list length is", len(dependencies), "and the list is:\n", dependencies)
}
assert.NoError(t, err)
assert.Equal(t, len(expectedDependenciesList), len(dependencies))
for _, eDependency := range expectedDependenciesList {
found := false
for aDependency, v := range dependencies {
Expand All @@ -110,9 +131,7 @@ func TestParseDependencies(t *testing.T) {
break
}
}
if !found {
t.Error("The expected dependency:", eDependency, "is missing from the actual dependencies list:\n", dependencies)
}
assert.True(t, found, "The expected dependency:", eDependency, "is missing from the actual dependencies list:\n", dependencies)
}
}

Expand All @@ -136,9 +155,7 @@ func TestAppendScopes(t *testing.T) {
}
for _, v := range scopes {
result := appendScopes(v.a, v.b)
if !assert.ElementsMatch(t, result, v.expected) {
t.Errorf("appendScopes(\"%s\",\"%s\") => '%s', want '%s'", v.a, v.b, result, v.expected)
}
assert.ElementsMatch(t, result, v.expected, "appendScopes(\"%s\",\"%s\") => '%s', want '%s'", v.a, v.b, result, v.expected)
}
}

Expand Down Expand Up @@ -299,7 +316,7 @@ func TestDependenciesTreeDifferentBetweenOKs(t *testing.T) {
dependencies, err := CalculateNpmDependenciesList("npm", projectPath, "bundle-dependencies", NpmTreeDepListParam{Args: npmArgs}, true, logger)
assert.NoError(t, err)

assert.Greaterf(t, len(dependencies), 0, "Error: dependencies are not found!")
assert.Greater(t, len(dependencies), 0, "Error: dependencies are not found!")

// Remove node_modules directory, then calculate dependencies by package-lock.
assert.NoError(t, utils.RemoveTempDir(filepath.Join(projectPath, "node_modules")))
Expand All @@ -308,7 +325,7 @@ func TestDependenciesTreeDifferentBetweenOKs(t *testing.T) {
assert.NoError(t, err)

// Asserting there is at least one dependency.
assert.Greaterf(t, len(dependencies), 0, "Error: dependencies are not found!")
assert.Greater(t, len(dependencies), 0, "Error: dependencies are not found!")
}

func TestNpmProdFlag(t *testing.T) {
Expand Down Expand Up @@ -387,7 +404,7 @@ func validateDependencies(t *testing.T, projectPath string, npmArgs []string) {
dependencies, err := CalculateNpmDependenciesList("npm", projectPath, "build-info-go-tests", NpmTreeDepListParam{Args: npmArgs}, true, logger)
assert.NoError(t, err)

assert.Greaterf(t, len(dependencies), 0, "Error: dependencies are not found!")
assert.Greater(t, len(dependencies), 0, "Error: dependencies are not found!")

// Remove node_modules directory, then calculate dependencies by package-lock.
assert.NoError(t, utils.RemoveTempDir(filepath.Join(projectPath, "node_modules")))
Expand All @@ -396,5 +413,5 @@ func validateDependencies(t *testing.T, projectPath string, npmArgs []string) {
assert.NoError(t, err)

// Asserting there is at least one dependency.
assert.Greaterf(t, len(dependencies), 0, "Error: dependencies are not found!")
assert.Greater(t, len(dependencies), 0, "Error: dependencies are not found!")
}
7 changes: 4 additions & 3 deletions build/yarn.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package build
import (
"errors"
"fmt"
"os"
"os/exec"

buildutils "github.com/jfrog/build-info-go/build/utils"
"github.com/jfrog/build-info-go/entities"
"github.com/jfrog/build-info-go/utils"
"github.com/jfrog/gofrog/version"
"golang.org/x/exp/slices"
"os"
"os/exec"
)

const minSupportedYarnVersion = "2.4.0"
Expand Down Expand Up @@ -49,7 +50,7 @@ func newYarnModule(srcPath string, containingBuild *Build) (*YarnModule, error)
}

// Read module name
packageInfo, err := buildutils.ReadPackageInfoFromPackageJson(srcPath, nil)
packageInfo, err := buildutils.ReadPackageInfoFromPackageJsonIfExist(srcPath, nil)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 4747a71

Please sign in to comment.