From c5e38d51558fb11ac588e34d95505acff072e83f Mon Sep 17 00:00:00 2001 From: Daniel Mikusa Date: Sun, 27 Feb 2022 22:46:17 -0500 Subject: [PATCH] Automatic build on the Tiny stack Prior to this PR, you would need to manually adjust cargo build argumets to build properly on the Tiny stack. This is a requirement because to run on the Tiny stack you need to compile against musl not glibc. If running on the tiny stack, this PR will automatically add the cargo build arguments `--target x86_64-unknown-linux-musl`. If the `--target` has already been set, it does not change the user provided value. If not running on the tiny stack, no `--target` is added. Signed-off-by: Daniel Mikusa --- cargo/build.go | 6 ++++-- cargo/cargo.go | 10 ++++++++++ cargo/cargo_test.go | 6 ++++-- runner/runners.go | 28 +++++++++++++++++++++++++++- runner/runners_test.go | 21 +++++++++++++++++++++ 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/cargo/build.go b/cargo/build.go index 3862a16..bd482dc 100644 --- a/cargo/build.go +++ b/cargo/build.go @@ -92,7 +92,8 @@ func (b Build) Build(context libcnb.BuildContext) (libcnb.BuildResult, error) { runner.WithCargoWorkspaceMembers(cargoWorkspaceMembers), runner.WithCargoInstallArgs(cargoInstallArgs), runner.WithExecutor(effect.NewExecutor()), - runner.WithLogger(b.Logger)) + runner.WithLogger(b.Logger), + runner.WithStack(context.StackID)) } cache := Cache{ @@ -107,7 +108,8 @@ func (b Build) Build(context libcnb.BuildContext) (libcnb.BuildResult, error) { WithApplicationPath(context.Application.Path), WithLogger(b.Logger), WithCargoService(service), - WithExcludeFolders(excludeFolders)) + WithExcludeFolders(excludeFolders), + WithStack(context.StackID)) if err != nil { return libcnb.BuildResult{}, fmt.Errorf("unable to create cargo layer contributor\n%w", err) } diff --git a/cargo/cargo.go b/cargo/cargo.go index 53fd3de..aa81b81 100644 --- a/cargo/cargo.go +++ b/cargo/cargo.go @@ -98,6 +98,14 @@ func WithExcludeFolders(f []string) Option { } } +// WithStack sets logger +func WithStack(stack string) Option { + return func(cargo Cargo) Cargo { + cargo.Stack = stack + return cargo + } +} + type Cargo struct { AdditionalMetadata map[string]interface{} ApplicationPath string @@ -108,6 +116,7 @@ type Cargo struct { LayerContributor libpak.LayerContributor Logger bard.Logger ExcludeFolders []string + Stack string WorkspaceMembers string } @@ -122,6 +131,7 @@ func NewCargo(options ...Option) (Cargo, error) { metadata := map[string]interface{}{ "additional-arguments": cargo.InstallArgs, "workspace-members": cargo.WorkspaceMembers, + "stack": cargo.Stack, } var err error diff --git a/cargo/cargo_test.go b/cargo/cargo_test.go index bbee30e..ecfa794 100644 --- a/cargo/cargo_test.go +++ b/cargo/cargo_test.go @@ -93,16 +93,18 @@ func testCargo(t *testing.T, context spec.G, it spec.S) { cargo.WithWorkspaceMembers("foo, bar"), cargo.WithApplicationPath(ctx.Application.Path), cargo.WithCargoService(service), - cargo.WithInstallArgs("--path=./todo --foo=bar --foo baz")) + cargo.WithInstallArgs("--path=./todo --foo=bar --foo baz"), + cargo.WithStack("foo-stack")) Expect(err).ToNot(HaveOccurred()) - Expect(r.LayerContributor.ExpectedMetadata).To(HaveLen(6)) + Expect(r.LayerContributor.ExpectedMetadata).To(HaveLen(7)) Expect(r.LayerContributor.ExpectedMetadata).To(HaveKeyWithValue("cargo-version", "1.2.3")) Expect(r.LayerContributor.ExpectedMetadata).To(HaveKeyWithValue("rust-version", "1.2.3")) Expect(r.LayerContributor.ExpectedMetadata).To(HaveKeyWithValue("additional-arguments", "--path=./todo --foo=bar --foo baz")) Expect(r.LayerContributor.ExpectedMetadata).To(HaveKeyWithValue("test", "expected-val")) Expect(r.LayerContributor.ExpectedMetadata).To(HaveKeyWithValue("workspace-members", "foo, bar")) + Expect(r.LayerContributor.ExpectedMetadata).To(HaveKeyWithValue("stack", "foo-stack")) // can't reliably check hash value because it differs every time due to temp path changing on every test run Expect(r.LayerContributor.ExpectedMetadata).To(HaveKey("files")) Expect(r.LayerContributor.ExpectedMetadata.(map[string]interface{})["files"]).To(HaveLen(64)) diff --git a/runner/runners.go b/runner/runners.go index 527fe9b..3ba888b 100644 --- a/runner/runners.go +++ b/runner/runners.go @@ -27,6 +27,7 @@ import ( "github.com/buildpacks/libcnb" "github.com/mattn/go-shellwords" + "github.com/paketo-buildpacks/libpak" "github.com/paketo-buildpacks/libpak/bard" "github.com/paketo-buildpacks/libpak/effect" "github.com/paketo-buildpacks/libpak/sherpa" @@ -80,7 +81,7 @@ func WithExecutor(executor effect.Executor) Option { } } -// WithLogger sets addition args to pass to cargo install +// WithLogger sets additional args to pass to cargo install func WithLogger(logger bard.Logger) Option { return func(runner CargoRunner) CargoRunner { runner.Logger = logger @@ -88,6 +89,14 @@ func WithLogger(logger bard.Logger) Option { } } +// WithStack sets the stack on which we're running +func WithStack(stack string) Option { + return func(runner CargoRunner) CargoRunner { + runner.Stack = stack + return runner + } +} + // CargoRunner can execute cargo via CLI type CargoRunner struct { CargoHome string @@ -95,6 +104,7 @@ type CargoRunner struct { CargoInstallArgs string Executor effect.Executor Logger bard.Logger + Stack string } type metadataTarget struct { @@ -335,6 +345,7 @@ func (c CargoRunner) BuildArgs(destLayer libcnb.Layer, defaultMemberPath string) args = append(args, envArgs...) args = append(args, "--color=never", fmt.Sprintf("--root=%s", destLayer.Path)) args = AddDefaultPath(args, defaultMemberPath) + args = AddDefaultTargetForTiny(args, c.Stack) return args, nil } @@ -376,6 +387,21 @@ func AddDefaultPath(args []string, defaultMemberPath string) []string { return append(args, fmt.Sprintf("--path=%s", defaultMemberPath)) } +// AddDefaultTargetForTiny will add --target=x86_64-unknown-linux-musl if the stack is Tiny and a `--target` is not already set +func AddDefaultTargetForTiny(args []string, stack string) []string { + if stack != libpak.TinyStackID { + return args + } + + for _, arg := range args { + if arg == "--target" || strings.HasPrefix(arg, "--target=") { + return args + } + } + + return append(args, "--target=x86_64-unknown-linux-musl") +} + // AsBOMEntry creates BOM entries from cargo dependencies func (c CargoRunner) AsBOMEntry() (libcnb.BOMEntry, error) { // TODO: read through cargo manifest and dump dependencies diff --git a/runner/runners_test.go b/runner/runners_test.go index efbdb97..958a639 100644 --- a/runner/runners_test.go +++ b/runner/runners_test.go @@ -30,6 +30,7 @@ import ( "github.com/buildpacks/libcnb" "github.com/paketo-community/cargo/runner" + "github.com/paketo-buildpacks/libpak" "github.com/paketo-buildpacks/libpak/bard" "github.com/paketo-buildpacks/libpak/effect" "github.com/paketo-buildpacks/libpak/effect/mocks" @@ -182,6 +183,26 @@ func testRunners(t *testing.T, context spec.G, it spec.S) { }) }) + context("set default --target argument", func() { + it("is specified by the user", func() { + Expect(runner.AddDefaultTargetForTiny([]string{"install", "--target"}, "foo")).To(Equal([]string{"install", "--target"})) + Expect(runner.AddDefaultTargetForTiny([]string{"install", "--target=test"}, "foo")).To(Equal([]string{"install", "--target=test"})) + Expect(runner.AddDefaultTargetForTiny([]string{"install", "--target", "test"}, "foo")).To(Equal([]string{"install", "--target", "test"})) + }) + + it("is not the tiny stack so no args are added", func() { + Expect(runner.AddDefaultTargetForTiny([]string{"install"}, "foo")).To(Equal([]string{"install"})) + Expect(runner.AddDefaultTargetForTiny([]string{"install", "--foo=bar"}, "foo")).To(Equal([]string{"install", "--foo=bar"})) + Expect(runner.AddDefaultTargetForTiny([]string{"install", "--foo", "bar"}, "foo")).To(Equal([]string{"install", "--foo", "bar"})) + }) + + it("is the tiny stack so default args are added", func() { + Expect(runner.AddDefaultTargetForTiny([]string{"install"}, libpak.TinyStackID)).To(Equal([]string{"install", "--target=x86_64-unknown-linux-musl"})) + Expect(runner.AddDefaultTargetForTiny([]string{"install", "--foo=bar"}, libpak.TinyStackID)).To(Equal([]string{"install", "--foo=bar", "--target=x86_64-unknown-linux-musl"})) + Expect(runner.AddDefaultTargetForTiny([]string{"install", "--foo", "bar"}, libpak.TinyStackID)).To(Equal([]string{"install", "--foo", "bar", "--target=x86_64-unknown-linux-musl"})) + }) + }) + context("when there is a valid Rust project", func() { it("builds correctly with defaults", func() { logBuf := bytes.Buffer{}