Skip to content

Commit

Permalink
leverage common functions from libnodejs (#339)
Browse files Browse the repository at this point in the history
* leverage common functions from libnodejs

- use package json parser
- use project path parser

to reduce code duplication

Signed-off-by: Michael Dawson <[email protected]>

* fix: replace use of os.Setenv with t.Setenv

- reduce code and chance of missing cleanup afterwards

Signed-off-by: Michael Dawson <[email protected]>

---------

Signed-off-by: Michael Dawson <[email protected]>
  • Loading branch information
mhdawson authored Aug 4, 2023
1 parent 0bd3ec1 commit 3642c2f
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 397 deletions.
9 changes: 4 additions & 5 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,21 @@ import (
"fmt"
"path/filepath"

"github.com/paketo-buildpacks/libnodejs"
"github.com/paketo-buildpacks/packit/v2"
"github.com/paketo-buildpacks/packit/v2/scribe"
)

func Build(pathParser PathParser, logger scribe.Emitter) packit.BuildFunc {
func Build(logger scribe.Emitter) packit.BuildFunc {
return func(context packit.BuildContext) (packit.BuildResult, error) {
logger.Title("%s %s", context.BuildpackInfo.Name, context.BuildpackInfo.Version)

projectPath, err := pathParser.Get(context.WorkingDir)
projectPath, err := libnodejs.FindProjectPath(context.WorkingDir)
if err != nil {
return packit.BuildResult{}, err
}

var pkg *PackageJson

pkg, err = NewPackageJsonFromPath(filepath.Join(projectPath, "package.json"))
pkg, err := libnodejs.ParsePackageJSON(projectPath)
if err != nil {
return packit.BuildResult{}, err
}
Expand Down
115 changes: 44 additions & 71 deletions build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package yarnstart_test

import (
"bytes"
"errors"
"fmt"
"os"
"path/filepath"
Expand All @@ -11,7 +10,6 @@ import (
"github.com/paketo-buildpacks/packit/v2"
"github.com/paketo-buildpacks/packit/v2/scribe"
yarnstart "github.com/paketo-buildpacks/yarn-start"
"github.com/paketo-buildpacks/yarn-start/fakes"
"github.com/sclevine/spec"

. "github.com/onsi/gomega"
Expand All @@ -25,7 +23,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
workingDir string
cnbDir string
buffer *bytes.Buffer
pathParser *fakes.PathParser

build packit.BuildFunc
)
Expand Down Expand Up @@ -54,10 +51,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
buffer = bytes.NewBuffer(nil)
logger := scribe.NewEmitter(buffer)

pathParser = &fakes.PathParser{}

pathParser.GetCall.Returns.ProjectPath = filepath.Join(workingDir, "some-project-dir")
build = yarnstart.Build(pathParser, logger)
build = yarnstart.Build(logger)
})

it.After(func() {
Expand All @@ -67,47 +61,49 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
})

it("returns a result that builds correctly", func() {
result, err := build(packit.BuildContext{
WorkingDir: workingDir,
CNBPath: cnbDir,
Stack: "some-stack",
BuildpackInfo: packit.BuildpackInfo{
Name: "Some Buildpack",
Version: "some-version",
},
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{},
},
Layers: packit.Layers{Path: layersDir},
it.Before(func() {
t.Setenv("BP_NODE_PROJECT_PATH", "some-project-dir")
})
Expect(err).NotTo(HaveOccurred())

Expect(result).To(Equal(packit.BuildResult{
Launch: packit.LaunchMetadata{
Processes: []packit.Process{
{
Type: "web",
Command: "bash",
Args: []string{
"-c",
fmt.Sprintf("cd %s/some-project-dir && some-prestart-command && some-start-command && some-poststart-command", workingDir),
it("default", func() {
result, err := build(packit.BuildContext{
WorkingDir: workingDir,
CNBPath: cnbDir,
Stack: "some-stack",
BuildpackInfo: packit.BuildpackInfo{
Name: "Some Buildpack",
Version: "some-version",
},
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{},
},
Layers: packit.Layers{Path: layersDir},
})
Expect(err).NotTo(HaveOccurred())

Expect(result).To(Equal(packit.BuildResult{
Launch: packit.LaunchMetadata{
Processes: []packit.Process{
{
Type: "web",
Command: "bash",
Args: []string{
"-c",
fmt.Sprintf("cd %s/some-project-dir && some-prestart-command && some-start-command && some-poststart-command", workingDir),
},
Default: true,
Direct: true,
},
Default: true,
Direct: true,
},
},
},
}))
Expect(pathParser.GetCall.Receives.Path).To(Equal(workingDir))
}))
})
})

context("when BP_LIVE_RELOAD_ENABLED=true in the build environment", func() {
it.Before(func() {
os.Setenv("BP_LIVE_RELOAD_ENABLED", "true")
})

it.After(func() {
os.Unsetenv("BP_LIVE_RELOAD_ENABLED")
t.Setenv("BP_LIVE_RELOAD_ENABLED", "true")
t.Setenv("BP_NODE_PROJECT_PATH", "some-project-dir")
})

it("adds a reloadable start command that ignores package manager files and makes it the default", func() {
Expand Down Expand Up @@ -154,7 +150,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Direct: true,
},
}))
Expect(pathParser.GetCall.Receives.Path).To(Equal(workingDir))
})
})

Expand All @@ -167,6 +162,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
}
}`), 0600)
Expect(err).NotTo(HaveOccurred())
t.Setenv("BP_NODE_PROJECT_PATH", "some-project-dir")
})

it("returns a result with a valid start command", func() {
Expand Down Expand Up @@ -212,6 +208,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
}
}`), 0600)
Expect(err).NotTo(HaveOccurred())
t.Setenv("BP_NODE_PROJECT_PATH", "some-project-dir")
})

it("returns a result with a valid start command", func() {
Expand Down Expand Up @@ -258,6 +255,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
}
}`), 0600)
Expect(err).NotTo(HaveOccurred())
t.Setenv("BP_NODE_PROJECT_PATH", "some-project-dir")
})

it("returns a result with a valid start command", func() {
Expand Down Expand Up @@ -297,7 +295,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {

context("when the project-path env var is not set", func() {
it.Before(func() {
pathParser.GetCall.Returns.ProjectPath = workingDir
err := os.WriteFile(filepath.Join(workingDir, "package.json"), []byte(`{
"scripts": {
"prestart": "some-prestart-command",
Expand Down Expand Up @@ -351,6 +348,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
context("when package.json does not exist", func() {
it.Before(func() {
Expect(os.RemoveAll(filepath.Join(workingDir, "some-project-dir", "package.json"))).To(Succeed())
t.Setenv("BP_NODE_PROJECT_PATH", "some-project-dir")
})

it("fails with the appropriate error", func() {
Expand All @@ -367,13 +365,14 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
},
Layers: packit.Layers{Path: layersDir},
})
Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("unable to open package.json: open %s", filepath.Join(workingDir, "some-project-dir", "package.json")))))
Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("open %s: no such file or directory", filepath.Join(workingDir, "some-project-dir", "package.json")))))
})
})

context("when package.json is malformed", func() {
it.Before(func() {
Expect(os.WriteFile(filepath.Join(workingDir, "some-project-dir", "package.json"), []byte("%%%"), os.ModePerm)).To(Succeed())
t.Setenv("BP_NODE_PROJECT_PATH", "some-project-dir")
})

it("fails with the appropriate error", func() {
Expand All @@ -390,40 +389,14 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
},
Layers: packit.Layers{Path: layersDir},
})
Expect(err).To(MatchError(ContainSubstring("unable to decode package.json: invalid character")))
})
})

context("when the path parser returns an error", func() {
it.Before(func() {
pathParser.GetCall.Returns.Err = errors.New("path-parser-error")
})

it("returns an error", func() {
_, err := build(packit.BuildContext{
WorkingDir: workingDir,
CNBPath: cnbDir,
Stack: "some-stack",
BuildpackInfo: packit.BuildpackInfo{
Name: "Some Buildpack",
Version: "some-version",
},
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{},
},
Layers: packit.Layers{Path: layersDir},
})
Expect(err).To(MatchError("path-parser-error"))
Expect(err).To(MatchError(ContainSubstring("unable to decode package.json invalid character '%' looking for beginning of value")))
})
})

context("when BP_LIVE_RELOAD_ENABLED is set to an invalid value", func() {
it.Before(func() {
os.Setenv("BP_LIVE_RELOAD_ENABLED", "not-a-bool")
})

it.After(func() {
os.Unsetenv("BP_LIVE_RELOAD_ENABLED")
t.Setenv("BP_LIVE_RELOAD_ENABLED", "not-a-bool")
t.Setenv("BP_NODE_PROJECT_PATH", "some-project-dir")
})

it("returns an error", func() {
Expand Down
21 changes: 10 additions & 11 deletions detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,17 @@ import (
"path/filepath"
"strconv"

"github.com/paketo-buildpacks/libnodejs"
"github.com/paketo-buildpacks/packit/v2"
"github.com/paketo-buildpacks/packit/v2/fs"
)

//go:generate faux --interface PathParser --output fakes/path_parser.go
type PathParser interface {
Get(path string) (projectPath string, err error)
}

// NoStartScriptError indicates that the targeted project does no have a start command in their package.json
const NoStartScriptError = "no start script in package.json"

func Detect(projectPathParser PathParser) packit.DetectFunc {
func Detect() packit.DetectFunc {
return func(context packit.DetectContext) (packit.DetectResult, error) {
projectPath, err := projectPathParser.Get(context.WorkingDir)
projectPath, err := libnodejs.FindProjectPath(context.WorkingDir)
if err != nil {
return packit.DetectResult{}, err
}
Expand All @@ -34,12 +30,15 @@ func Detect(projectPathParser PathParser) packit.DetectFunc {
return packit.DetectResult{}, packit.Fail.WithMessage("no 'yarn.lock' found in the project path %s", projectPath)
}

var pkg *PackageJson
if pkg, err = NewPackageJsonFromPath(filepath.Join(projectPath, "package.json")); err != nil {
return packit.DetectResult{}, err
pkg, err := libnodejs.ParsePackageJSON(projectPath)
if err != nil {
if os.IsNotExist(err) {
return packit.DetectResult{}, packit.Fail.WithMessage("no 'package.json' found in project path %s", projectPath)
}
return packit.DetectResult{}, fmt.Errorf("failed to open package.json: %w", err)
}

if !pkg.hasStartCommand() {
if !pkg.HasStartScript() {
return packit.DetectResult{}, packit.Fail.WithMessage(NoStartScriptError)
}

Expand Down
Loading

0 comments on commit 3642c2f

Please sign in to comment.