diff --git a/.gitignore b/.gitignore index c886796..36bab64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ !integration/testdata .bin +bin/ build .idea/ linux darwin -windows \ No newline at end of file +windows diff --git a/install_process.go b/install_process.go index 4c61f04..69c2cd8 100644 --- a/install_process.go +++ b/install_process.go @@ -39,8 +39,17 @@ func (p PoetryInstallProcess) Execute(workingDir, targetPath, cachePath string) if !exists { installOnly = "main" } + poetryVersion, exists := os.LookupEnv("BP_POETRY_VERSION") + if !exists { + poetryVersion = "2.*" + } + installCmd := []string{"sync"} + // Can be remove once support for poetry v1 is removed + if strings.HasPrefix(poetryVersion, "1") { + installCmd = []string{"install", "--sync"} + } - args := []string{"install", "--only", installOnly} + args := append(installCmd, "--only", installOnly) env := append( os.Environ(), diff --git a/install_process_test.go b/install_process_test.go index 086e89b..c3a1134 100644 --- a/install_process_test.go +++ b/install_process_test.go @@ -66,6 +66,7 @@ func testInstallProcess(t *testing.T, context spec.G, it spec.S) { Expect(os.RemoveAll(packagesLayerPath)).To(Succeed()) Expect(os.RemoveAll(cacheLayerPath)).To(Succeed()) Expect(os.RemoveAll(workingDir)).To(Succeed()) + os.Unsetenv("BP_POETRY_VERSION") }) context("Execute", func() { @@ -78,7 +79,7 @@ func testInstallProcess(t *testing.T, context spec.G, it spec.S) { Expect(executableInvocations[0]).To(MatchFields(IgnoreExtras, Fields{ "Args": Equal([]string{ - "install", "--only", "main", + "sync", "--only", "main", }), "Dir": Equal(workingDir), "Env": ContainElements([]string{ @@ -100,7 +101,47 @@ func testInstallProcess(t *testing.T, context spec.G, it spec.S) { Expect(venvDir).To(Equal("/some/path/to/some/venv")) Expect(buffer.String()).To(ContainLines( - fmt.Sprintf(" Running 'POETRY_CACHE_DIR=%s POETRY_VIRTUALENVS_PATH=%s poetry install --only main'", cacheLayerPath, packagesLayerPath), + fmt.Sprintf(" Running 'POETRY_CACHE_DIR=%s POETRY_VIRTUALENVS_PATH=%s poetry sync --only main'", cacheLayerPath, packagesLayerPath), + " //some/path/xyz/../to/some/venv//", + " stderr output", + )) + }) + + it("runs installation v1", func() { + os.Setenv("BP_POETRY_VERSION", "1.8.5") + venvDir, err := poetryInstallProcess.Execute(workingDir, packagesLayerPath, cacheLayerPath) + Expect(err).NotTo(HaveOccurred()) + + Expect(executable.ExecuteCall.CallCount).To(Equal(2)) + Expect(executableInvocations).To(HaveLen(2)) + + Expect(executableInvocations[0]).To(MatchFields(IgnoreExtras, Fields{ + "Args": Equal([]string{ + "install", "--sync", "--only", "main", + }), + "Dir": Equal(workingDir), + "Env": ContainElements([]string{ + fmt.Sprintf("BP_POETRY_VERSION=%s", "1.8.5"), + fmt.Sprintf("POETRY_VIRTUALENVS_PATH=%s", packagesLayerPath), + fmt.Sprintf("POETRY_CACHE_DIR=%s", cacheLayerPath), + }), + })) + + Expect(executableInvocations[1]).To(MatchFields(IgnoreExtras, Fields{ + "Args": Equal([]string{ + "env", "info", "--path", + }), + "Dir": Equal(workingDir), + "Env": ContainElements([]string{ + fmt.Sprintf("BP_POETRY_VERSION=%s", "1.8.5"), + fmt.Sprintf("POETRY_VIRTUALENVS_PATH=%s", packagesLayerPath), + fmt.Sprintf("POETRY_CACHE_DIR=%s", cacheLayerPath), + }), + })) + + Expect(venvDir).To(Equal("/some/path/to/some/venv")) + Expect(buffer.String()).To(ContainLines( + fmt.Sprintf(" Running 'POETRY_CACHE_DIR=%s POETRY_VIRTUALENVS_PATH=%s poetry install --sync --only main'", cacheLayerPath, packagesLayerPath), " //some/path/xyz/../to/some/venv//", " stderr output", )) diff --git a/integration/default_test.go b/integration/default_test.go index 519cf4f..f96ed30 100644 --- a/integration/default_test.go +++ b/integration/default_test.go @@ -74,7 +74,7 @@ func testDefault(t *testing.T, context spec.G, it spec.S) { Expect(logs).To(ContainLines(" Executing build process")) Expect(logs).To(ContainLines( MatchRegexp(fmt.Sprintf( - " Running 'POETRY_CACHE_DIR=/layers/%s/cache POETRY_VIRTUALENVS_PATH=/layers/%s/poetry-venv poetry install --only main'", + " Running 'POETRY_CACHE_DIR=/layers/%s/cache POETRY_VIRTUALENVS_PATH=/layers/%s/poetry-venv poetry sync --only main'", strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"), strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"), )), @@ -134,7 +134,68 @@ func testDefault(t *testing.T, context spec.G, it spec.S) { Expect(logs).To(ContainLines(" Executing build process")) Expect(logs).To(ContainLines( MatchRegexp(fmt.Sprintf( - " Running 'POETRY_CACHE_DIR=/layers/%s/cache POETRY_VIRTUALENVS_PATH=/layers/%s/poetry-venv poetry install --only main,dev'", + " Running 'POETRY_CACHE_DIR=/layers/%s/cache POETRY_VIRTUALENVS_PATH=/layers/%s/poetry-venv poetry sync --only main,dev'", + strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"), + strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"), + )), + )) + Expect(logs).To(ContainLines( + MatchRegexp(` \- Installing ipython \(\d+\.\d+\.\d+\)`), + )) + Expect(logs).ToNot(ContainLines( + MatchRegexp(` \- Installing ruff \(\d+\.\d+\.\d+\)`), + )) + Expect(logs).To(ContainLines(MatchRegexp(` Completed in \d+\.\d+`))) + Expect(logs).To(ContainLines( + " Configuring build environment", + MatchRegexp(fmt.Sprintf(` PATH -> "/layers/%s/poetry-venv/default-app-.*-py\d+\.\d+/bin:\$PATH"`, strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"))), + MatchRegexp(fmt.Sprintf(` POETRY_VIRTUALENVS_PATH -> "/layers/%s/poetry-venv"`, strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"))), + MatchRegexp(fmt.Sprintf(` PYTHONPATH -> "/layers/%s/poetry-venv/default-app-.*-py\d+\.\d+/lib/python\d+\.\d+/site-packages:\$PYTHONPATH"`, strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"))), + "", + " Configuring launch environment", + MatchRegexp(fmt.Sprintf(` PATH -> "/layers/%s/poetry-venv/default-app-.*-py\d+\.\d+/bin:\$PATH"`, strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"))), + MatchRegexp(fmt.Sprintf(` POETRY_VIRTUALENVS_PATH -> "/layers/%s/poetry-venv"`, strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"))), + MatchRegexp(fmt.Sprintf(` PYTHONPATH -> "/layers/%s/poetry-venv/default-app-.*-py\d+\.\d+/lib/python\d+\.\d+/site-packages:\$PYTHONPATH"`, strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"))), + )) + + container, err = docker.Container.Run. + WithCommand("gunicorn server:app"). + WithEnv(map[string]string{"PORT": "8080"}). + WithPublish("8080"). + Execute(image.ID) + Expect(err).ToNot(HaveOccurred()) + + Eventually(container).Should(BeAvailable()) + Eventually(container).Should(Serve(ContainSubstring("Hello, World!")).OnPort(8080)) + }) + + it("builds and runs successfully with develop dependencies (poetry v1)", func() { + var err error + var logs fmt.Stringer + + image, logs, err = pack.WithNoColor().Build. + WithPullPolicy("never"). + WithEnv(map[string]string{ + "BP_POETRY_VERSION": "1.8.5", + "BP_POETRY_INSTALL_ONLY": "main,dev", + }). + WithBuildpacks( + settings.Buildpacks.CPython.Online, + settings.Buildpacks.Pip.Online, + settings.Buildpacks.Poetry.Online, + settings.Buildpacks.PoetryInstall.Online, + settings.Buildpacks.BuildPlan.Online, + ). + Execute(name, source) + Expect(err).ToNot(HaveOccurred(), logs.String) + + Expect(logs).To(ContainLines( + MatchRegexp(fmt.Sprintf(`%s \d+\.\d+\.\d+`, buildpackInfo.Buildpack.Name)), + )) + Expect(logs).To(ContainLines(" Executing build process")) + Expect(logs).To(ContainLines( + MatchRegexp(fmt.Sprintf( + " Running 'POETRY_CACHE_DIR=/layers/%s/cache POETRY_VIRTUALENVS_PATH=/layers/%s/poetry-venv poetry install --sync --only main,dev'", strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"), strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"), )), diff --git a/integration/testdata/default_app/project.toml b/integration/testdata/default_app/project.toml new file mode 100644 index 0000000..774a644 --- /dev/null +++ b/integration/testdata/default_app/project.toml @@ -0,0 +1,4 @@ +[build] +exclude = [ + ".venv", +] \ No newline at end of file