From 982d5e374a034ecdea0bdc627ae54212dbe944f7 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Fri, 3 Oct 2025 13:55:19 +0300 Subject: [PATCH 1/4] feat: requiring cpython in non rhel distros --- constants.go | 5 +++-- detect.go | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/constants.go b/constants.go index 9b3be401..e9a8cb87 100644 --- a/constants.go +++ b/constants.go @@ -1,8 +1,9 @@ package nodeengine const ( - Node = "node" - Npm = "npm" + Node = "node" + Npm = "npm" + Cpython = "cpython" DepKey = "dependency-sha" BuildKey = "build" diff --git a/detect.go b/detect.go index b8904ac9..ecf2f04e 100644 --- a/detect.go +++ b/detect.go @@ -2,6 +2,7 @@ package nodeengine import ( "os" + "os/exec" "path/filepath" "github.com/paketo-buildpacks/packit/v2" @@ -16,6 +17,8 @@ type VersionParser interface { type BuildPlanMetadata struct { Version string `toml:"version"` VersionSource string `toml:"version-source"` + Build bool `toml:"build"` + Launch bool `toml:"launch"` } func Detect(nvmrcParser, nodeVersionParser VersionParser) packit.DetectFunc { @@ -80,6 +83,20 @@ func Detect(nvmrcParser, nodeVersionParser VersionParser) packit.DetectFunc { }) } + targetOs := os.Getenv("CNB_TARGET_DISTRO_NAME") + _, pythonNotFound := exec.LookPath("python") + + installPython := (targetOs != "rhel" && pythonNotFound != nil) + if installPython { + requirements = append(requirements, packit.BuildPlanRequirement{ + Name: Cpython, + Metadata: BuildPlanMetadata{ + Build: true, + Launch: false, + }, + }) + } + return packit.DetectResult{ Plan: packit.BuildPlan{ Provides: []packit.BuildPlanProvision{ From b40b555002b9792c274da230dadf4c30b9565605 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Fri, 3 Oct 2025 19:08:40 +0300 Subject: [PATCH 2/4] fix: integration tests to include proeprly python --- integration.json | 6 ++++-- integration/init_test.go | 8 ++++++++ integration/inspector_test.go | 1 + integration/offline_test.go | 1 + integration/openssl_test.go | 2 ++ integration/optimize_memory_test.go | 1 + integration/project_path_test.go | 1 + integration/provides_test.go | 1 + integration/reuse_layer_rebuild_test.go | 4 ++++ integration/simple_app_test.go | 6 ++++++ 10 files changed, 29 insertions(+), 2 deletions(-) diff --git a/integration.json b/integration.json index 7e1bf3fe..afcdb31b 100644 --- a/integration.json +++ b/integration.json @@ -1,6 +1,8 @@ { "build-plan": "github.com/paketo-community/build-plan", "builders": [ - "index.docker.io/paketobuildpacks/builder-jammy-buildpackless-base:latest" - ] + "index.docker.io/paketobuildpacks/builder-jammy-buildpackless-base:latest", + "index.docker.io/paketobuildpacks/ubuntu-noble-builder-buildpackless:latest" + ], + "cpython": "github.com/paketo-buildpacks/cpython" } diff --git a/integration/init_test.go b/integration/init_test.go index 149d5685..aa13419c 100644 --- a/integration/init_test.go +++ b/integration/init_test.go @@ -29,6 +29,9 @@ var settings struct { Processes struct { Online string } + Cpython struct { + Online string + } } Buildpack struct { @@ -38,6 +41,7 @@ var settings struct { Config struct { BuildPlan string `json:"build-plan"` + Cpython string `json:"cpython"` } } @@ -73,6 +77,10 @@ func TestIntegration(t *testing.T) { Execute(root) Expect(err).NotTo(HaveOccurred()) + settings.Buildpacks.Cpython.Online, err = buildpackStore.Get. + Execute(settings.Config.Cpython) + Expect(err).ToNot(HaveOccurred()) + tmpBuildpackDir, err := os.MkdirTemp("", "node-engine-outdated-deps") Expect(err).NotTo(HaveOccurred()) diff --git a/integration/inspector_test.go b/integration/inspector_test.go index 1a9478c9..ad866eee 100644 --- a/integration/inspector_test.go +++ b/integration/inspector_test.go @@ -52,6 +52,7 @@ 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, ). diff --git a/integration/offline_test.go b/integration/offline_test.go index 2ad7a3a7..41c952bf 100644 --- a/integration/offline_test.go +++ b/integration/offline_test.go @@ -56,6 +56,7 @@ func testOffline(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.Offline, settings.Buildpacks.BuildPlan.Online, ). diff --git a/integration/openssl_test.go b/integration/openssl_test.go index b9537f5c..4dee57f6 100644 --- a/integration/openssl_test.go +++ b/integration/openssl_test.go @@ -67,6 +67,7 @@ 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, ). @@ -106,6 +107,7 @@ 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, ). diff --git a/integration/optimize_memory_test.go b/integration/optimize_memory_test.go index 5cf7dab4..237b0777 100644 --- a/integration/optimize_memory_test.go +++ b/integration/optimize_memory_test.go @@ -53,6 +53,7 @@ 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, ). diff --git a/integration/project_path_test.go b/integration/project_path_test.go index 701475cf..9cf098f3 100644 --- a/integration/project_path_test.go +++ b/integration/project_path_test.go @@ -60,6 +60,7 @@ 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, ). diff --git a/integration/provides_test.go b/integration/provides_test.go index 5b922772..125d8e45 100644 --- a/integration/provides_test.go +++ b/integration/provides_test.go @@ -55,6 +55,7 @@ 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, ). diff --git a/integration/reuse_layer_rebuild_test.go b/integration/reuse_layer_rebuild_test.go index 22e6783c..00bb53c5 100644 --- a/integration/reuse_layer_rebuild_test.go +++ b/integration/reuse_layer_rebuild_test.go @@ -72,6 +72,7 @@ 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, ). @@ -137,6 +138,7 @@ 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, ). @@ -203,6 +205,7 @@ 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, ). @@ -270,6 +273,7 @@ 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, ). diff --git a/integration/simple_app_test.go b/integration/simple_app_test.go index 381c85c9..869392c2 100644 --- a/integration/simple_app_test.go +++ b/integration/simple_app_test.go @@ -71,6 +71,7 @@ func testSimple(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, ). @@ -183,6 +184,7 @@ func testSimple(t *testing.T, context spec.G, it spec.S) { WithPullPolicy("never"). WithEnv(map[string]string{"NODE_ENV": "development", "NODE_VERBOSE": "true"}). WithBuildpacks( + settings.Buildpacks.Cpython.Online, settings.Buildpacks.NodeEngine.Online, settings.Buildpacks.BuildPlan.Online, ). @@ -248,6 +250,7 @@ func testSimple(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, ). @@ -334,6 +337,7 @@ func testSimple(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, ). @@ -415,6 +419,7 @@ func testSimple(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.Deprecated, settings.Buildpacks.BuildPlan.Online, ). @@ -443,6 +448,7 @@ func testSimple(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, ). From 469da15d8377409b3f63418ed86f9c8ff5808120 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Fri, 3 Oct 2025 23:03:07 +0300 Subject: [PATCH 3/4] fix: offline test for cpython --- integration/init_test.go | 8 ++++++- integration/offline_test.go | 2 +- integration/reuse_layer_rebuild_test.go | 31 ++++++++++++++----------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/integration/init_test.go b/integration/init_test.go index aa13419c..d59c9ad5 100644 --- a/integration/init_test.go +++ b/integration/init_test.go @@ -30,7 +30,8 @@ var settings struct { Online string } Cpython struct { - Online string + Online string + Offline string } } @@ -81,6 +82,11 @@ func TestIntegration(t *testing.T) { Execute(settings.Config.Cpython) Expect(err).ToNot(HaveOccurred()) + settings.Buildpacks.Cpython.Offline, err = buildpackStore.Get. + WithOfflineDependencies(). + Execute(settings.Config.Cpython) + Expect(err).ToNot(HaveOccurred()) + tmpBuildpackDir, err := os.MkdirTemp("", "node-engine-outdated-deps") Expect(err).NotTo(HaveOccurred()) diff --git a/integration/offline_test.go b/integration/offline_test.go index 41c952bf..4e043d82 100644 --- a/integration/offline_test.go +++ b/integration/offline_test.go @@ -56,7 +56,7 @@ func testOffline(t *testing.T, context spec.G, it spec.S) { image, logs, err = pack.WithNoColor().Build. WithPullPolicy("never"). WithBuildpacks( - settings.Buildpacks.Cpython.Online, + settings.Buildpacks.Cpython.Offline, settings.Buildpacks.NodeEngine.Offline, settings.Buildpacks.BuildPlan.Online, ). diff --git a/integration/reuse_layer_rebuild_test.go b/integration/reuse_layer_rebuild_test.go index 00bb53c5..0c98bbd7 100644 --- a/integration/reuse_layer_rebuild_test.go +++ b/integration/reuse_layer_rebuild_test.go @@ -81,9 +81,11 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) { imageIDs[firstImage.ID] = struct{}{} - Expect(firstImage.Buildpacks).To(HaveLen(2)) - Expect(firstImage.Buildpacks[0].Key).To(Equal(settings.Buildpack.ID)) - Expect(firstImage.Buildpacks[0].Layers).To(HaveKey("node")) + //print first image content + + 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(logs).To(ContainLines( fmt.Sprintf("%s 1.2.3", settings.Buildpack.Name), @@ -147,9 +149,9 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) { imageIDs[secondImage.ID] = struct{}{} - 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(secondImage.Buildpacks).To(HaveLen(3)) + Expect(secondImage.Buildpacks[1].Key).To(Equal(settings.Buildpack.ID)) + Expect(secondImage.Buildpacks[1].Layers).To(HaveKey("node")) Expect(logs).To(ContainLines( fmt.Sprintf("%s 1.2.3", settings.Buildpack.Name), @@ -183,7 +185,8 @@ 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["node"].SHA).To(Equal(firstImage.Buildpacks[0].Layers["node"].SHA)) + 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)) }) }) @@ -215,9 +218,9 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) { imageIDs[firstImage.ID] = struct{}{} - 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(firstImage.Buildpacks).To(HaveLen(3)) + Expect(firstImage.Buildpacks[1].Key).To(Equal(settings.Buildpack.ID)) + Expect(firstImage.Buildpacks[1].Layers).To(HaveKey("node")) Expect(logs).To(ContainLines( fmt.Sprintf("%s 1.2.3", settings.Buildpack.Name), @@ -283,9 +286,9 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) { imageIDs[secondImage.ID] = struct{}{} - 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(secondImage.Buildpacks).To(HaveLen(3)) + Expect(secondImage.Buildpacks[1].Key).To(Equal(settings.Buildpack.ID)) + Expect(secondImage.Buildpacks[1].Layers).To(HaveKey("node")) Expect(logs).To(ContainLines( fmt.Sprintf("%s 1.2.3", settings.Buildpack.Name), @@ -345,7 +348,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["node"].SHA).NotTo(Equal(firstImage.Buildpacks[0].Layers["node"].SHA)) + Expect(secondImage.Buildpacks[1].Layers["node"].SHA).NotTo(Equal(firstImage.Buildpacks[1].Layers["node"].SHA)) }) }) } From cfc7e664f66e8c9a433351927730e301929b6df8 Mon Sep 17 00:00:00 2001 From: Jerico Pena Date: Sun, 12 Oct 2025 14:35:49 +0100 Subject: [PATCH 4/4] Update integration/reuse_layer_rebuild_test.go remove comment --- integration/reuse_layer_rebuild_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/integration/reuse_layer_rebuild_test.go b/integration/reuse_layer_rebuild_test.go index 0c98bbd7..90aa0537 100644 --- a/integration/reuse_layer_rebuild_test.go +++ b/integration/reuse_layer_rebuild_test.go @@ -81,7 +81,6 @@ func testReusingLayerRebuild(t *testing.T, context spec.G, it spec.S) { imageIDs[firstImage.ID] = struct{}{} - //print first image content Expect(firstImage.Buildpacks).To(HaveLen(3)) Expect(firstImage.Buildpacks[1].Key).To(Equal(settings.Buildpack.ID))