Skip to content

Commit

Permalink
Moved nvmrc detection to nodejs-cnb
Browse files Browse the repository at this point in the history
[#163528537]

Co-authored-by: Danny Joyce <[email protected]>
  • Loading branch information
dfreilich and Danny Joyce committed Feb 13, 2019
1 parent a1fa1f1 commit b3d7297
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 211 deletions.
128 changes: 0 additions & 128 deletions cmd/detect/detector.go

This file was deleted.

50 changes: 39 additions & 11 deletions cmd/detect/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/cloudfoundry/libcfbuildpack/helper"

Expand All @@ -20,6 +21,11 @@ func main() {
os.Exit(100)
}

if err := context.BuildPlan.Init(); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Failed to initialize Build Plan: %s\n", err)
os.Exit(101)
}

code, err := runDetect(context)
if err != nil {
context.Logger.Info(err.Error())
Expand All @@ -30,33 +36,33 @@ func main() {

func runDetect(context detect.Detect) (int, error) {
packageJSON := filepath.Join(context.Application.Root, "package.json")

if exists, err := helper.FileExists(packageJSON); err != nil {
return context.Fail(), fmt.Errorf("error checking filepath: %s", packageJSON)
} else if !exists {
return context.Fail(), fmt.Errorf(`no "package.json" found at: %s`, packageJSON)
}

nvmrcNodeVersion, err := LoadNvmrc(context)
if err != nil {
return context.Fail(), fmt.Errorf(`unable to parse ".nvmrc": %s`, err.Error())
}

packageJSONVersion, err := node.GetVersion(packageJSON)
if err != nil {
return context.Fail(), fmt.Errorf(`unable to parse "package.json": %s`, err.Error())
}

logs := WarnNodeEngine(nvmrcNodeVersion, packageJSONVersion)
for _, line := range logs {
context.Logger.Info(line)
curNodeVersion := ""
if nodeDep, found := context.BuildPlan[node.Dependency]; found {
curNodeVersion = nodeDep.Version
}

if exists, err := helper.FileExists(filepath.Join(context.Application.Root, ".nvmrc")); err != nil {
return context.Fail(), err
} else if exists {
warnNodeEngine(curNodeVersion, packageJSONVersion, context)
}

version := ""
if packageJSONVersion != "" {
version = packageJSONVersion
} else if nvmrcNodeVersion != "" {
version = nvmrcNodeVersion
} else if curNodeVersion != "" {
version = curNodeVersion
}

return context.Pass(buildplan.BuildPlan{
Expand All @@ -69,3 +75,25 @@ func runDetect(context detect.Detect) (int, error) {
},
})
}

func warnNodeEngine(nvmrcNodeVersion string, packageJSONNodeVersion string, context detect.Detect) []string {
docsLink := "http://docs.cloudfoundry.org/buildpacks/node/node-tips.html"

var logs []string
if nvmrcNodeVersion != "" && packageJSONNodeVersion == "" {
context.Logger.Info("Using the node version specified in your .nvmrc See: %s", docsLink)
}
if packageJSONNodeVersion != "" && nvmrcNodeVersion != "" {
context.Logger.Info("Node version in .nvmrc ignored in favor of 'engines' field in package.json")
}
if packageJSONNodeVersion == "" && nvmrcNodeVersion == "" {
context.Logger.Info("Node version not specified in package.json or .nvmrc. See: %s", docsLink)
}
if packageJSONNodeVersion == "*" {
context.Logger.Info("Dangerous semver range (*) in engines.node. See: %s", docsLink)
}
if strings.HasPrefix(packageJSONNodeVersion, ">") {
context.Logger.Info("Dangerous semver range (>) in engines.node. See: %s", docsLink)
}
return logs
}
83 changes: 11 additions & 72 deletions cmd/detect/main_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"errors"
"fmt"
"path/filepath"
"testing"
Expand Down Expand Up @@ -59,23 +58,17 @@ func testDetect(t *testing.T, when spec.G, it spec.S) {
})

when("When .nvmrc is present", func() {
when("nvmrc is empty", func() {
it("should fail", func() {
test.WriteFile(t, filepath.Join(factory.Detect.Application.Root, ".nvmrc"), "")
code, err := runDetect(factory.Detect)
Expect(err).To(HaveOccurred())
Expect(code).To(Equal(detect.FailStatusCode))
})
})

when("nvmrc is present and engines field in package.json is present", func() {
it("selects the version from the engines field in packages.json", func() {
packageJSONVersion := "10.0.0"
packageJSONString := fmt.Sprintf(`{"engines": {"node" : "%s"}}`, packageJSONVersion)
test.WriteFile(t, filepath.Join(factory.Detect.Application.Root, "package.json"), packageJSONString)

nvmrcString := "10.2.3"
test.WriteFile(t, filepath.Join(factory.Detect.Application.Root, ".nvmrc"), nvmrcString)
nvmrcVersion := "10.2.3"
factory.AddBuildPlan(node.Dependency, buildplan.Dependency{
Version: nvmrcVersion,
Metadata: buildplan.Metadata{"launch": true},
})

buildplan := getStandardBuildplanWithNodeVersion(packageJSONVersion)
runDetectAndExpectBuildplan(factory, buildplan)
Expand All @@ -87,71 +80,17 @@ func testDetect(t *testing.T, when spec.G, it spec.S) {
packageJSONString := fmt.Sprintf(`{"engines": {"node" : "%s"}}`, "")
test.WriteFile(t, filepath.Join(factory.Detect.Application.Root, "package.json"), packageJSONString)

nvmrcString := "10.2.3"
test.WriteFile(t, filepath.Join(factory.Detect.Application.Root, ".nvmrc"), nvmrcString)
nvmrcVersion := "10.2.3"
factory.AddBuildPlan(node.Dependency, buildplan.Dependency{
Version: nvmrcVersion,
Metadata: buildplan.Metadata{"launch": true},
})

buildplan := getStandardBuildplanWithNodeVersion(nvmrcString)
buildplan := getStandardBuildplanWithNodeVersion(nvmrcVersion)
runDetectAndExpectBuildplan(factory, buildplan)
})
})
})

when("there are .nvmrc contents", func() {
when("the .nvmrc contains only digits", func() {
it("will trim and transform nvmrc to appropriate semver for Masterminds semver library", func() {
testCases := [][]string{
{"10", "10.*.*"},
{"10.2", "10.2.*"},
{"v10", "10.*.*"},
{"10.2.3", "10.2.3"},
{"v10.2.3", "10.2.3"},
{"10.1.1", "10.1.1"},
}

for _, testCase := range testCases {
test.WriteFile(t, filepath.Join(factory.Detect.Application.Root, ".nvmrc"), testCase[0])
Expect(LoadNvmrc(factory.Detect)).To(Equal(testCase[1]), fmt.Sprintf("failed for test case %s : %s", testCase[0], testCase[1]))
}
})
})

when("the .nvmrc contains lts/something", func() {
it("will read and trim lts versions to appropriate semver for Masterminds semver library", func() {
testCases := [][]string{
{"lts/*", "10.*.*"},
{"lts/argon", "4.*.*"},
{"lts/boron", "6.*.*"},
{"lts/carbon", "8.*.*"},
{"lts/dubnium", "10.*.*"},
}

for _, testCase := range testCases {
test.WriteFile(t, filepath.Join(factory.Detect.Application.Root, ".nvmrc"), testCase[0])
Expect(LoadNvmrc(factory.Detect)).To(Equal(testCase[1]), fmt.Sprintf("failed for test case %s : %s", testCase[0], testCase[1]))
}
})
})

when("the .nvmrc contains 'node'", func() {
it("should read and trim lts versions", func() {
test.WriteFile(t, filepath.Join(factory.Detect.Application.Root, ".nvmrc"), "node")
Expect(LoadNvmrc(factory.Detect)).To(Equal("*"))
})
})

when("given an invalid .nvmrc", func() {
it("validate should be fail", func() {
invalidVersions := []string{"11.4.x", "invalid", "~1.1.2", ">11.0", "< 11.4.2", "^1.2.3", "11.*.*", "10.1.X", "lts/invalidname"}
InvalidVersionError := errors.New("invalid version Invalid Semantic Version specified in .nvmrc")
for _, version := range invalidVersions {
test.WriteFile(t, filepath.Join(factory.Detect.Application.Root, ".nvmrc"), version)
parsedVersion, err := LoadNvmrc(factory.Detect)
Expect(err).To(Equal(InvalidVersionError))
Expect(parsedVersion).To(BeEmpty())
}
})
})
})
}

func runDetectAndExpectBuildplan(factory *test.DetectFactory, buildplan buildplan.BuildPlan) {
Expand Down

0 comments on commit b3d7297

Please sign in to comment.