diff --git a/buildpack.toml b/buildpack.toml index 024b00e5..56383cd5 100644 --- a/buildpack.toml +++ b/buildpack.toml @@ -16,255 +16,255 @@ api = "0.8" [[order.group]] id = "paketo-buildpacks/ca-certificates" optional = true - version = "3.2.5" + version = "3.3.0" [[order.group]] id = "paketo-buildpacks/watchexec" optional = true - version = "2.5.4" + version = "2.6.0" [[order.group]] id = "paketo-buildpacks/cpython" - version = "1.2.1" + version = "1.3.0" [[order.group]] id = "paketo-buildpacks/pip" - version = "0.14.0" + version = "0.14.1" [[order.group]] id = "paketo-buildpacks/pipenv" - version = "1.3.0" + version = "1.4.0" [[order.group]] id = "paketo-buildpacks/pipenv-install" - version = "0.6.0" + version = "0.6.1" [[order.group]] id = "paketo-buildpacks/python-start" - version = "0.12.0" + version = "0.12.1" [[order.group]] id = "paketo-buildpacks/procfile" optional = true - version = "5.2.1" + version = "5.3.0" [[order.group]] id = "paketo-buildpacks/environment-variables" optional = true - version = "4.1.3" + version = "4.2.0" [[order.group]] id = "paketo-buildpacks/image-labels" optional = true - version = "4.1.3" + version = "4.2.0" [[order]] [[order.group]] id = "paketo-buildpacks/ca-certificates" optional = true - version = "3.2.5" + version = "3.3.0" [[order.group]] id = "paketo-buildpacks/watchexec" optional = true - version = "2.5.4" + version = "2.6.0" [[order.group]] id = "paketo-buildpacks/cpython" - version = "1.2.1" + version = "1.3.0" [[order.group]] id = "paketo-buildpacks/pip" - version = "0.14.0" + version = "0.14.1" [[order.group]] id = "paketo-buildpacks/pip-install" - version = "0.5.0" + version = "0.5.1" [[order.group]] id = "paketo-buildpacks/python-start" - version = "0.12.0" + version = "0.12.1" [[order.group]] id = "paketo-buildpacks/procfile" optional = true - version = "5.2.1" + version = "5.3.0" [[order.group]] id = "paketo-buildpacks/environment-variables" optional = true - version = "4.1.3" + version = "4.2.0" [[order.group]] id = "paketo-buildpacks/image-labels" optional = true - version = "4.1.3" + version = "4.2.0" [[order]] [[order.group]] id = "paketo-buildpacks/ca-certificates" optional = true - version = "3.2.5" + version = "3.3.0" [[order.group]] id = "paketo-buildpacks/watchexec" optional = true - version = "2.5.4" + version = "2.6.0" [[order.group]] id = "paketo-buildpacks/miniconda" - version = "0.6.0" + version = "0.6.1" [[order.group]] id = "paketo-buildpacks/conda-env-update" - version = "0.5.0" + version = "0.5.1" [[order.group]] id = "paketo-buildpacks/python-start" - version = "0.12.0" + version = "0.12.1" [[order.group]] id = "paketo-buildpacks/procfile" optional = true - version = "5.2.1" + version = "5.3.0" [[order.group]] id = "paketo-buildpacks/environment-variables" optional = true - version = "4.1.3" + version = "4.2.0" [[order.group]] id = "paketo-buildpacks/image-labels" optional = true - version = "4.1.3" + version = "4.2.0" [[order]] [[order.group]] id = "paketo-buildpacks/ca-certificates" optional = true - version = "3.2.5" + version = "3.3.0" [[order.group]] id = "paketo-buildpacks/watchexec" optional = true - version = "2.5.4" + version = "2.6.0" [[order.group]] id = "paketo-buildpacks/cpython" - version = "1.2.1" + version = "1.3.0" [[order.group]] id = "paketo-buildpacks/pip" - version = "0.14.0" + version = "0.14.1" [[order.group]] id = "paketo-buildpacks/poetry" - version = "0.3.0" + version = "0.3.1" [[order.group]] id = "paketo-buildpacks/poetry-install" - version = "0.3.0" + version = "0.3.1" [[order.group]] id = "paketo-buildpacks/poetry-run" - version = "0.4.0" + version = "0.4.1" [[order.group]] id = "paketo-buildpacks/procfile" optional = true - version = "5.2.1" + version = "5.3.0" [[order.group]] id = "paketo-buildpacks/environment-variables" optional = true - version = "4.1.3" + version = "4.2.0" [[order.group]] id = "paketo-buildpacks/image-labels" optional = true - version = "4.1.3" + version = "4.2.0" [[order]] [[order.group]] id = "paketo-buildpacks/ca-certificates" optional = true - version = "3.2.5" + version = "3.3.0" [[order.group]] id = "paketo-buildpacks/watchexec" optional = true - version = "2.5.4" + version = "2.6.0" [[order.group]] id = "paketo-buildpacks/cpython" - version = "1.2.1" + version = "1.3.0" [[order.group]] id = "paketo-buildpacks/pip" - version = "0.14.0" + version = "0.14.1" [[order.group]] id = "paketo-buildpacks/poetry" - version = "0.3.0" + version = "0.3.1" [[order.group]] id = "paketo-buildpacks/poetry-install" - version = "0.3.0" + version = "0.3.1" [[order.group]] id = "paketo-buildpacks/python-start" - version = "0.12.0" + version = "0.12.1" [[order.group]] id = "paketo-buildpacks/procfile" optional = true - version = "5.2.1" + version = "5.3.0" [[order.group]] id = "paketo-buildpacks/environment-variables" optional = true - version = "4.1.3" + version = "4.2.0" [[order.group]] id = "paketo-buildpacks/image-labels" optional = true - version = "4.1.3" + version = "4.2.0" [[order]] [[order.group]] id = "paketo-buildpacks/ca-certificates" optional = true - version = "3.2.5" + version = "3.3.0" [[order.group]] id = "paketo-buildpacks/watchexec" optional = true - version = "2.5.4" + version = "2.6.0" [[order.group]] id = "paketo-buildpacks/cpython" - version = "1.2.1" + version = "1.3.0" [[order.group]] id = "paketo-buildpacks/python-start" - version = "0.12.0" + version = "0.12.1" [[order.group]] id = "paketo-buildpacks/procfile" optional = true - version = "5.2.1" + version = "5.3.0" [[order.group]] id = "paketo-buildpacks/environment-variables" optional = true - version = "4.1.3" + version = "4.2.0" [[order.group]] id = "paketo-buildpacks/image-labels" optional = true - version = "4.1.3" + version = "4.2.0" diff --git a/integration/init_test.go b/integration/init_test.go index a49a5b42..380e668f 100644 --- a/integration/init_test.go +++ b/integration/init_test.go @@ -28,12 +28,13 @@ func TestIntegration(t *testing.T) { SetDefaultEventuallyTimeout(10 * time.Second) - suite := spec.New("Integration", spec.Report(report.Terminal{})) + suite := spec.New("Integration", spec.Parallel(), spec.Report(report.Terminal{})) suite("Conda", testConda) suite("Pip", testPip) suite("Pipenv", testPipenv) suite("PoetryDepOnly", testPoetryDepOnly) suite("PoetryRun", testPoetryRun) suite("NoPackageManager", testNoPackageManager) + suite("ReproducibleBuilds", testReproducibleBuilds) suite.Run(t) } diff --git a/integration/reproducible_builds_test.go b/integration/reproducible_builds_test.go new file mode 100644 index 00000000..ef9e2e3d --- /dev/null +++ b/integration/reproducible_builds_test.go @@ -0,0 +1,272 @@ +package integration_test + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/paketo-buildpacks/occam" + "github.com/sclevine/spec" + + . "github.com/onsi/gomega" +) + +func testReproducibleBuilds(t *testing.T, context spec.G, it spec.S) { + var ( + Expect = NewWithT(t).Expect + + pack occam.Pack + docker occam.Docker + ) + + it.Before(func() { + pack = occam.NewPack() + docker = occam.NewDocker() + }) + + context("when building a conda app", func() { + var ( + image occam.Image + + name string + source string + ) + + it.Before(func() { + var err error + name, err = occam.RandomName() + Expect(err).NotTo(HaveOccurred()) + + source, err = occam.Source(filepath.Join("testdata", "conda")) + Expect(err).NotTo(HaveOccurred()) + }) + + it.After(func() { + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + Expect(os.RemoveAll(source)).To(Succeed()) + }) + + it("creates a two identical images from the same input", func() { + var err error + var logs fmt.Stringer + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + firstID := image.ID + + // Delete the first image + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + WithClearCache(). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + Expect(firstID).To(Equal(image.ID)) + }) + }) + + context("when building a python app with no package manager", func() { + var ( + image occam.Image + + name string + source string + ) + + it.Before(func() { + var err error + name, err = occam.RandomName() + Expect(err).NotTo(HaveOccurred()) + + source, err = occam.Source(filepath.Join("testdata", "no_package_manager")) + Expect(err).NotTo(HaveOccurred()) + }) + + it.After(func() { + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + Expect(os.RemoveAll(source)).To(Succeed()) + }) + + it("creates a two identical images from the same input", func() { + var err error + var logs fmt.Stringer + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + firstID := image.ID + + // Delete the first image + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + WithClearCache(). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + Expect(firstID).To(Equal(image.ID)) + }) + }) + + context("when building a pip app", func() { + var ( + image occam.Image + + name string + source string + ) + + it.Before(func() { + var err error + name, err = occam.RandomName() + Expect(err).NotTo(HaveOccurred()) + + source, err = occam.Source(filepath.Join("testdata", "pip")) + Expect(err).NotTo(HaveOccurred()) + }) + + it.After(func() { + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + Expect(os.RemoveAll(source)).To(Succeed()) + }) + + it("creates a two identical images from the same input", func() { + var err error + var logs fmt.Stringer + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + firstID := image.ID + + // Delete the first image + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + WithClearCache(). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + Expect(firstID).To(Equal(image.ID)) + }) + }) + + context("when building a pipenv app", func() { + var ( + image occam.Image + + name string + source string + ) + + it.Before(func() { + var err error + name, err = occam.RandomName() + Expect(err).NotTo(HaveOccurred()) + + source, err = occam.Source(filepath.Join("testdata", "pipenv")) + Expect(err).NotTo(HaveOccurred()) + }) + + it.After(func() { + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + Expect(os.RemoveAll(source)).To(Succeed()) + }) + + it("creates a two identical images from the same input", func() { + var err error + var logs fmt.Stringer + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + firstID := image.ID + + // Delete the first image + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + WithClearCache(). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + Expect(firstID).To(Equal(image.ID)) + }) + }) + + context("when building an app with poetry dependency management", func() { + var ( + image occam.Image + + name string + source string + ) + + it.Before(func() { + var err error + name, err = occam.RandomName() + Expect(err).NotTo(HaveOccurred()) + + source, err = occam.Source(filepath.Join("testdata", "poetry-dep-only")) + Expect(err).NotTo(HaveOccurred()) + }) + + it.After(func() { + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + Expect(os.RemoveAll(source)).To(Succeed()) + }) + + it("creates a two identical images from the same input", func() { + var err error + var logs fmt.Stringer + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + firstID := image.ID + + // Delete the first image + Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed()) + Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed()) + + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(pythonBuildpack). + WithPullPolicy("never"). + WithClearCache(). + Execute(name, source) + Expect(err).NotTo(HaveOccurred(), logs.String()) + + Expect(firstID).To(Equal(image.ID)) + }) + }) +} diff --git a/package.toml b/package.toml index b77da095..39dbbea0 100644 --- a/package.toml +++ b/package.toml @@ -3,49 +3,49 @@ uri = "build/buildpack.tgz" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/cpython@1.2.1" + uri = "urn:cnb:registry:paketo-buildpacks/cpython@1.3.0" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/pip@0.14.0" + uri = "urn:cnb:registry:paketo-buildpacks/pip@0.14.1" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/pipenv@1.3.0" + uri = "urn:cnb:registry:paketo-buildpacks/pipenv@1.4.0" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/pipenv-install@0.6.0" + uri = "urn:cnb:registry:paketo-buildpacks/pipenv-install@0.6.1" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/pip-install@0.5.0" + uri = "urn:cnb:registry:paketo-buildpacks/pip-install@0.5.1" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/python-start@0.12.0" + uri = "urn:cnb:registry:paketo-buildpacks/python-start@0.12.1" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/miniconda@0.6.0" + uri = "urn:cnb:registry:paketo-buildpacks/miniconda@0.6.1" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/conda-env-update@0.5.0" + uri = "urn:cnb:registry:paketo-buildpacks/conda-env-update@0.5.1" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/poetry@0.3.0" + uri = "urn:cnb:registry:paketo-buildpacks/poetry@0.3.1" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/poetry-install@0.3.0" + uri = "urn:cnb:registry:paketo-buildpacks/poetry-install@0.3.1" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/poetry-run@0.4.0" + uri = "urn:cnb:registry:paketo-buildpacks/poetry-run@0.4.1" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/procfile@5.2.1" + uri = "urn:cnb:registry:paketo-buildpacks/procfile@5.3.0" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/environment-variables@4.1.3" + uri = "urn:cnb:registry:paketo-buildpacks/environment-variables@4.2.0" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/ca-certificates@3.2.5" + uri = "urn:cnb:registry:paketo-buildpacks/ca-certificates@3.3.0" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/image-labels@4.1.3" + uri = "urn:cnb:registry:paketo-buildpacks/image-labels@4.2.0" [[dependencies]] - uri = "urn:cnb:registry:paketo-buildpacks/watchexec@2.5.4" + uri = "urn:cnb:registry:paketo-buildpacks/watchexec@2.6.0"