From 355f0b9e241c261f10e07c95ad8396b6802b5c68 Mon Sep 17 00:00:00 2001 From: Daniel Mikusa Date: Thu, 4 Apr 2024 14:38:01 -0400 Subject: [PATCH] Modify carton package to work with targets We recently added targets to the `include-files` list in `buildpack.toml`. The referenced files get packaged up into the buildpack. What we added were some files prefixed with `linux//...`. These files get put into that location within the generated buildpack directory. This is to work with a new version of pack that packages multi-arch images. It packages up whatever is under each architecture directory into the image specific to that architecture. What's happened is that we now have non-architecture dependent files like the README and LICENSE which are not being included in the images. These files also need to be prefixed with the path for each architecture. Instead of putting a lot of duplicate entries into the `include-files` list, what this PR does is to take any file not prefixed with `linux/` and duplicate it for all of the detected architectures. The PR determines the list of target architectures by looking at the `include-files` list and pulling out all of the distinct `linux/`'s that it sees. This isn't the best implementation but it's all we can do with the v1.x branch of libpak because the target metadata is not present in that version of libcnb. In libpak 2.x, we'll be able to read the target list directly from `buildpack.toml` and use that instead, which is a better option. Signed-off-by: Daniel Mikusa --- carton/package.go | 30 +++++++++++++++++++- carton/package_test.go | 63 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/carton/package.go b/carton/package.go index f58b3bf..71e764e 100644 --- a/carton/package.go +++ b/carton/package.go @@ -22,6 +22,7 @@ import ( "path/filepath" "regexp" "sort" + "strings" "text/template" "github.com/BurntSushi/toml" @@ -97,10 +98,37 @@ func (p Package) Create(options ...Option) { return } + logger.Debugf("IncludeFiles: %+v", metadata.IncludeFiles) + + supportedTargets := []string{} + for _, i := range metadata.IncludeFiles { + if strings.HasPrefix(i, "linux/") { + parts := strings.SplitN(i, "/", 3) + if len(parts) < 3 { + // this shouldn't happen, but if it does for some reason just ignore it + // this entry is not a properly formatted target + continue + } + supportedTargets = append(supportedTargets, fmt.Sprintf("%s/%s", parts[0], parts[1])) + } + } + + if len(supportedTargets) == 0 { + logger.Info("No supported targets found, defaulting to old format") + } + + logger.Debugf("Supported targets: %+v", supportedTargets) + entries := map[string]string{} for _, i := range metadata.IncludeFiles { - entries[i] = filepath.Join(p.Source, i) + if len(supportedTargets) == 0 || strings.HasPrefix(i, "linux/") || i == "buildpack.toml" { + entries[i] = filepath.Join(p.Source, i) + } else { + for _, target := range supportedTargets { + entries[fmt.Sprintf("%s/%s", target, i)] = filepath.Join(p.Source, i) + } + } } logger.Debugf("Include files: %+v", entries) diff --git a/carton/package_test.go b/carton/package_test.go index 0649f26..2a03e2f 100644 --- a/carton/package_test.go +++ b/carton/package_test.go @@ -100,7 +100,68 @@ include-files = [ Expect(e.Dir).To(Equal(path)) }) - it("includes include_files", func() { + context("has a buildpack.toml with target specific include files", func() { + it.Before(func() { + Expect(os.WriteFile(filepath.Join(path, "buildpack.toml"), []byte(` +api = "0.0.0" + +[buildpack] +name = "test-name" +version = "{{.version}}" + +[[metadata.dependencies]] +id = "test-id" +name = "test-name" +version = "1.1.1" +uri = "test-uri" +sha256 = "test-sha256" +stacks = [ "test-stack" ] + + [[metadata.dependencies.licenses]] + type = "test-type" + uri = "test-uri" + +[metadata] +pre-package = "test-pre-package" +include-files = [ + "buildpack.toml", + "README", + "LICENSE", + "linux/amd64/bin/just-once", + "linux/arm64/bin/also-just-once" +] +`), 0644)).To(Succeed()) + }) + + it("includes include_files using the original format", func() { + carton.Package{ + Source: path, + Destination: "test-destination", + }.Create( + carton.WithEntryWriter(entryWriter), + carton.WithExecutor(executor), + carton.WithExitHandler(exitHandler)) + + Expect(entryWriter.Calls[0].Arguments[0]).To(Equal(filepath.Join(path, "buildpack.toml"))) + Expect(entryWriter.Calls[0].Arguments[1]).To(Equal(filepath.Join("test-destination", "buildpack.toml"))) + + Expect(entryWriter.Calls[1].Arguments[0]).To(Equal(filepath.Join(path, "LICENSE"))) + Expect(entryWriter.Calls[1].Arguments[1]).To(Equal(filepath.Join("test-destination", "linux/amd64/LICENSE"))) + Expect(entryWriter.Calls[2].Arguments[0]).To(Equal(filepath.Join(path, "README"))) + Expect(entryWriter.Calls[2].Arguments[1]).To(Equal(filepath.Join("test-destination", "linux/amd64/README"))) + Expect(entryWriter.Calls[3].Arguments[0]).To(Equal(filepath.Join(path, "linux/amd64/bin/just-once"))) + Expect(entryWriter.Calls[3].Arguments[1]).To(Equal(filepath.Join("test-destination", "linux/amd64/bin/just-once"))) + + Expect(entryWriter.Calls[4].Arguments[0]).To(Equal(filepath.Join(path, "LICENSE"))) + Expect(entryWriter.Calls[4].Arguments[1]).To(Equal(filepath.Join("test-destination", "linux/arm64/LICENSE"))) + Expect(entryWriter.Calls[5].Arguments[0]).To(Equal(filepath.Join(path, "README"))) + Expect(entryWriter.Calls[5].Arguments[1]).To(Equal(filepath.Join("test-destination", "linux/arm64/README"))) + Expect(entryWriter.Calls[6].Arguments[0]).To(Equal(filepath.Join(path, "linux/arm64/bin/also-just-once"))) + Expect(entryWriter.Calls[6].Arguments[1]).To(Equal(filepath.Join("test-destination", "linux/arm64/bin/also-just-once"))) + }) + }) + + it("includes include_files using the target format", func() { carton.Package{ Source: path, Destination: "test-destination",