Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

## `docker.io/paketobuildpacks/node-engine`

The Node Engine CNB provides the Node binary distribution. The buildpack
The Node Engine CNB provides the Node binary distribution. The buildpack
installs the Node binary distribution onto the `$PATH` which makes it available
for subsequent buildpacks and in the final running container. Examples of
for subsequent buildpacks and in the final running container. Examples of
buildpacks that might use the Node binary distribution are the [NPM
CNB](https://github.com/paketo-buildpacks/npm) and [Yarn Install
CNB](https://github.com/paketo-buildpacks/yarn-install)
Expand Down Expand Up @@ -159,14 +159,34 @@ $BPL_DEBUG_PORT="9009"

For more information on debugging, see [Official Documentation](https://nodejs.org/en/docs/guides/debugging-getting-started)

### Include python during build process

To require [python](https://github.com/paketo-buildpacks/cpython) during the build process, set the `BP_NODE_INCLUDE_BUILD_PYTHON` environment variable at build time. You can set it either directly:

```shell
pack build my-app --builder paketobuildpcks/builder-jammy-base \
--env BP_NODE_INCLUDE_BUILD_PYTHON=true
```

or through a [`project.toml`](https://github.com/buildpacks/spec/blob/main/extensions/project-descriptor.md) file.

This is necessary for compiling native modules during `npm install` process, as `node-gyp` requires Python to complete this process.

Note that the `BP_NODE_INCLUDE_BUILD_PYTHON` variable is not required in the following cases:

- The [builder-jammy-full](https://github.com/paketo-buildpacks/builder-jammy-full) builder as python is already provided by the build image.
- The UBI builders ([ubi-8-builder](https://github.com/paketo-buildpacks/builder-ubi8-base), [ubi-9-builder](https://github.com/paketo-buildpacks/ubi-9-builder), etc.), as Python is being provided by the extension during build time.

## Run Tests

To run all unit tests, run:

```
./scripts/unit.sh
```

To run all integration tests, run:

```
/scripts/integration.sh
```
12 changes: 8 additions & 4 deletions detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package nodeengine

import (
"os"
"os/exec"
"path/filepath"

"github.com/paketo-buildpacks/packit/v2"
Expand Down Expand Up @@ -83,10 +82,15 @@ func Detect(nvmrcParser, nodeVersionParser VersionParser) packit.DetectFunc {
})
}

targetOs := os.Getenv("CNB_TARGET_DISTRO_NAME")
_, pythonNotFound := exec.LookPath("python")
bpNodeIncludeBuildPython, bpNodeIncludeBuildPythonExists := os.LookupEnv("BP_NODE_INCLUDE_BUILD_PYTHON")

installPython := false
if bpNodeIncludeBuildPythonExists && (bpNodeIncludeBuildPython == "" || bpNodeIncludeBuildPython == "true") {
installPython = true
} else if bpNodeIncludeBuildPythonExists && bpNodeIncludeBuildPython == "false" {
installPython = false
}

installPython := (targetOs != "rhel" && pythonNotFound != nil)
if installPython {
requirements = append(requirements, packit.BuildPlanRequirement{
Name: Cpython,
Expand Down
130 changes: 130 additions & 0 deletions detect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,136 @@ func testDetect(t *testing.T, context spec.G, it spec.S) {
})
})

context("when $BP_NODE_INCLUDE_BUILD_PYTHON env variable is present", func() {
it.After(func() {
os.Unsetenv("BP_NODE_INCLUDE_BUILD_PYTHON")
})

it("has been set to true, it should include cpython buildpack", func() {
os.Setenv("BP_NODE_INCLUDE_BUILD_PYTHON", "true")

result, err := detect(packit.DetectContext{
WorkingDir: "/working-dir",
})
Expect(err).NotTo(HaveOccurred())
Expect(result.Plan).To(Equal(packit.BuildPlan{
Provides: []packit.BuildPlanProvision{
{Name: nodeengine.Node},
},
Requires: []packit.BuildPlanRequirement{
{
Name: nodeengine.Cpython,
Metadata: nodeengine.BuildPlanMetadata{
Build: true,
Launch: false,
},
},
},
Or: []packit.BuildPlan{
{
Provides: []packit.BuildPlanProvision{
{Name: nodeengine.Node},
{Name: nodeengine.Npm},
},
Requires: []packit.BuildPlanRequirement{
{
Name: nodeengine.Cpython,
Metadata: nodeengine.BuildPlanMetadata{
Build: true,
Launch: false,
},
},
},
},
},
}))
})

it("has no value, it should include cpython buildpack", func() {
os.Setenv("BP_NODE_INCLUDE_BUILD_PYTHON", "")

result, err := detect(packit.DetectContext{
WorkingDir: "/working-dir",
})
Expect(err).NotTo(HaveOccurred())
Expect(result.Plan).To(Equal(packit.BuildPlan{
Provides: []packit.BuildPlanProvision{
{Name: nodeengine.Node},
},
Requires: []packit.BuildPlanRequirement{
{
Name: nodeengine.Cpython,
Metadata: nodeengine.BuildPlanMetadata{
Build: true,
Launch: false,
},
},
},
Or: []packit.BuildPlan{
{
Provides: []packit.BuildPlanProvision{
{Name: nodeengine.Node},
{Name: nodeengine.Npm},
},
Requires: []packit.BuildPlanRequirement{
{
Name: nodeengine.Cpython,
Metadata: nodeengine.BuildPlanMetadata{
Build: true,
Launch: false,
},
},
},
},
},
}))
})

it("has been set to false, it does not include cpython buildpack", func() {
os.Setenv("BP_NODE_INCLUDE_BUILD_PYTHON", "false")

result, err := detect(packit.DetectContext{
WorkingDir: "/working-dir",
})
Expect(err).NotTo(HaveOccurred())
Expect(result.Plan).To(Equal(packit.BuildPlan{
Provides: []packit.BuildPlanProvision{
{Name: nodeengine.Node},
},
Or: []packit.BuildPlan{
{
Provides: []packit.BuildPlanProvision{
{Name: nodeengine.Node},
{Name: nodeengine.Npm},
},
},
},
}))
})

it("has been set to random string, it does not include cpython buildpack", func() {
os.Setenv("BP_NODE_INCLUDE_BUILD_PYTHON", "random-string")

result, err := detect(packit.DetectContext{
WorkingDir: "/working-dir",
})
Expect(err).NotTo(HaveOccurred())
Expect(result.Plan).To(Equal(packit.BuildPlan{
Provides: []packit.BuildPlanProvision{
{Name: nodeengine.Node},
},
Or: []packit.BuildPlan{
{
Provides: []packit.BuildPlanProvision{
{Name: nodeengine.Node},
{Name: nodeengine.Npm},
},
},
},
}))
})
})

context("failure cases", func() {
context("when the dir specified by BP_NODE_PROJECT_PATH does not exist", func() {
var workingDir string
Expand Down
1 change: 0 additions & 1 deletion integration/inspector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ func testInspector(t *testing.T, context spec.G, it spec.S) {
image, logs, err = pack.WithNoColor().Build.
WithPullPolicy("never").
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.Processes.Online,
).
Expand Down
5 changes: 4 additions & 1 deletion integration/offline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ func testOffline(t *testing.T, context spec.G, it spec.S) {
settings.Buildpacks.NodeEngine.Offline,
settings.Buildpacks.BuildPlan.Online,
).
WithEnv(map[string]string{"BP_NODE_OPTIMIZE_MEMORY": "true"}).
WithEnv(map[string]string{
"BP_NODE_OPTIMIZE_MEMORY": "true",
"BP_NODE_INCLUDE_BUILD_PYTHON": "true",
}).
WithNetwork("none").
Execute(name, source)

Expand Down
2 changes: 0 additions & 2 deletions integration/openssl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ func testOpenSSL(t *testing.T, context spec.G, it spec.S) {

image, logs, err = pack.WithNoColor().Build.
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.BuildPlan.Online,
).
Expand Down Expand Up @@ -107,7 +106,6 @@ func testOpenSSL(t *testing.T, context spec.G, it spec.S) {

image, logs, err = pack.WithNoColor().Build.
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.BuildPlan.Online,
).
Expand Down
1 change: 0 additions & 1 deletion integration/optimize_memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ func testOptimizeMemory(t *testing.T, context spec.G, it spec.S) {
image, logs, err = pack.WithNoColor().Build.
WithPullPolicy("never").
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.Processes.Online,
).
Expand Down
1 change: 0 additions & 1 deletion integration/project_path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ func testProjectPath(t *testing.T, context spec.G, it spec.S) {
image, logs, err = pack.WithNoColor().Build.
WithPullPolicy("never").
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.BuildPlan.Online,
).
Expand Down
1 change: 0 additions & 1 deletion integration/provides_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func testProvides(t *testing.T, context spec.G, it spec.S) {
image, logs, err = pack.WithNoColor().Build.
WithPullPolicy("never").
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.BuildPlan.Online,
).
Expand Down
34 changes: 14 additions & 20 deletions integration/reuse_layer_rebuild_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {
firstImage, logs, err = pack.WithNoColor().Build.
WithPullPolicy("never").
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.BuildPlan.Online,
).
Expand All @@ -81,10 +80,9 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {

imageIDs[firstImage.ID] = struct{}{}


Expect(firstImage.Buildpacks).To(HaveLen(3))
Expect(firstImage.Buildpacks[1].Key).To(Equal(settings.Buildpack.ID))
Expect(firstImage.Buildpacks[1].Layers).To(HaveKey("node"))
Expect(firstImage.Buildpacks).To(HaveLen(2))
Expect(firstImage.Buildpacks[0].Key).To(Equal(settings.Buildpack.ID))
Expect(firstImage.Buildpacks[0].Layers).To(HaveKey("node"))

Expect(logs).To(ContainLines(
fmt.Sprintf("%s 1.2.3", settings.Buildpack.Name),
Expand Down Expand Up @@ -139,7 +137,6 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {
secondImage, logs, err = pack.WithNoColor().Build.
WithPullPolicy("never").
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.BuildPlan.Online,
).
Expand All @@ -148,9 +145,9 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {

imageIDs[secondImage.ID] = struct{}{}

Expect(secondImage.Buildpacks).To(HaveLen(3))
Expect(secondImage.Buildpacks[1].Key).To(Equal(settings.Buildpack.ID))
Expect(secondImage.Buildpacks[1].Layers).To(HaveKey("node"))
Expect(secondImage.Buildpacks).To(HaveLen(2))
Expect(secondImage.Buildpacks[0].Key).To(Equal(settings.Buildpack.ID))
Expect(secondImage.Buildpacks[0].Layers).To(HaveKey("node"))

Expect(logs).To(ContainLines(
fmt.Sprintf("%s 1.2.3", settings.Buildpack.Name),
Expand Down Expand Up @@ -184,8 +181,7 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {
Expect(err).NotTo(HaveOccurred())
Expect(content).To(ContainSubstring("hello world"))

Expect(secondImage.Buildpacks[0].Layers["cpython"].SHA).To(Equal(firstImage.Buildpacks[0].Layers["cpython"].SHA))
Expect(secondImage.Buildpacks[1].Layers["node"].SHA).To(Equal(firstImage.Buildpacks[1].Layers["node"].SHA))
Expect(secondImage.Buildpacks[0].Layers["node"].SHA).To(Equal(firstImage.Buildpacks[0].Layers["node"].SHA))
})
})

Expand All @@ -207,7 +203,6 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {
firstImage, logs, err = pack.WithNoColor().Build.
WithPullPolicy("never").
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.BuildPlan.Online,
).
Expand All @@ -217,9 +212,9 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {

imageIDs[firstImage.ID] = struct{}{}

Expect(firstImage.Buildpacks).To(HaveLen(3))
Expect(firstImage.Buildpacks[1].Key).To(Equal(settings.Buildpack.ID))
Expect(firstImage.Buildpacks[1].Layers).To(HaveKey("node"))
Expect(firstImage.Buildpacks).To(HaveLen(2))
Expect(firstImage.Buildpacks[0].Key).To(Equal(settings.Buildpack.ID))
Expect(firstImage.Buildpacks[0].Layers).To(HaveKey("node"))

Expect(logs).To(ContainLines(
fmt.Sprintf("%s 1.2.3", settings.Buildpack.Name),
Expand Down Expand Up @@ -275,7 +270,6 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {
secondImage, logs, err = pack.WithNoColor().Build.
WithPullPolicy("never").
WithBuildpacks(
settings.Buildpacks.Cpython.Online,
settings.Buildpacks.NodeEngine.Online,
settings.Buildpacks.BuildPlan.Online,
).
Expand All @@ -285,9 +279,9 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {

imageIDs[secondImage.ID] = struct{}{}

Expect(secondImage.Buildpacks).To(HaveLen(3))
Expect(secondImage.Buildpacks[1].Key).To(Equal(settings.Buildpack.ID))
Expect(secondImage.Buildpacks[1].Layers).To(HaveKey("node"))
Expect(secondImage.Buildpacks).To(HaveLen(2))
Expect(secondImage.Buildpacks[0].Key).To(Equal(settings.Buildpack.ID))
Expect(secondImage.Buildpacks[0].Layers).To(HaveKey("node"))

Expect(logs).To(ContainLines(
fmt.Sprintf("%s 1.2.3", settings.Buildpack.Name),
Expand Down Expand Up @@ -347,7 +341,7 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) {
Expect(err).NotTo(HaveOccurred())
Expect(content).To(ContainSubstring("hello world"))

Expect(secondImage.Buildpacks[1].Layers["node"].SHA).NotTo(Equal(firstImage.Buildpacks[1].Layers["node"].SHA))
Expect(secondImage.Buildpacks[0].Layers["node"].SHA).NotTo(Equal(firstImage.Buildpacks[0].Layers["node"].SHA))
})
})
}
Loading
Loading