Skip to content

Commit

Permalink
Merge pull request #1141 from buildpacks/jkutner/fix-1121
Browse files Browse the repository at this point in the history
Added workspace mount point as option to build
Signed-off-by: David Freilich <[email protected]>
  • Loading branch information
dfreilich authored Apr 28, 2021
2 parents 4d4f310 + 21a7929 commit bfd0c73
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 3 deletions.
4 changes: 4 additions & 0 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ type BuildOptions struct {
// The lifecycle image that will be used for the analysis, restore and export phases
// when using an untrusted builder.
LifecycleImage string

// The location at which to mount the AppDir in the build image.
Workspace string
}

// ProxyConfig specifies proxy setting to be set as environment variables in a container.
Expand Down Expand Up @@ -303,6 +306,7 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error {
DefaultProcessType: opts.DefaultProcessType,
FileFilter: fileFilter,
CacheImage: opts.CacheImage,
Workspace: opts.Workspace,
}

lifecycleVersion := ephemeralBuilder.LifecycleDescriptor().Info.Version
Expand Down
11 changes: 11 additions & 0 deletions build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ func testBuild(t *testing.T, when spec.G, it spec.S) {
})

when("#Build", func() {
when("Workspace option", func() {
it("uses the specified dir", func() {
h.AssertNil(t, subject.Build(context.TODO(), BuildOptions{
Workspace: "app",
Builder: defaultBuilderName,
Image: "example.com/some/repo:tag",
}))
h.AssertEq(t, fakeLifecycle.Opts.Workspace, "app")
})
})

when("Image option", func() {
it("is required", func() {
h.AssertError(t, subject.Build(context.TODO(), BuildOptions{
Expand Down
6 changes: 5 additions & 1 deletion internal/build/lifecycle_execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func NewLifecycleExecution(logger logging.Logger, docker client.CommonAPIClient,
platformAPI: latestSupportedPlatformAPI,
opts: opts,
os: osType,
mountPaths: mountPathsForOS(osType),
mountPaths: mountPathsForOS(osType, opts.Workspace),
}

return exec, nil
Expand Down Expand Up @@ -90,6 +90,10 @@ func (l *LifecycleExecution) AppPath() string {
return l.opts.AppPath
}

func (l LifecycleExecution) AppDir() string {
return l.mountPaths.appDir()
}

func (l *LifecycleExecution) AppVolume() string {
return l.appVolume
}
Expand Down
26 changes: 26 additions & 0 deletions internal/build/lifecycle_execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"testing"
"time"

Expand Down Expand Up @@ -135,6 +136,7 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) {

lifecycle, err := build.NewLifecycleExecution(logger, docker, opts)
h.AssertNil(t, err)
h.AssertEq(t, filepath.Base(lifecycle.AppDir()), "workspace")

err = lifecycle.Run(context.Background(), func(execution *build.LifecycleExecution) build.PhaseFactory {
return fakePhaseFactory
Expand Down Expand Up @@ -183,6 +185,30 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) {
})
})

when("Run with workspace dir", func() {
it("succeeds", func() {
opts := build.LifecycleOptions{
Publish: false,
ClearCache: false,
RunImage: "test",
Image: imageName,
Builder: fakeBuilder,
TrustBuilder: false,
Workspace: "app",
UseCreator: true,
}

lifecycle, err := build.NewLifecycleExecution(logger, docker, opts)
h.AssertNil(t, err)
h.AssertEq(t, filepath.Base(lifecycle.AppDir()), "app")

err = lifecycle.Run(context.Background(), func(execution *build.LifecycleExecution) build.PhaseFactory {
return fakePhaseFactory
})
h.AssertNil(t, err)
})
})

when("Error cases", func() {
when("passed invalid cache-image", func() {
it("fails", func() {
Expand Down
1 change: 1 addition & 0 deletions internal/build/lifecycle_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type LifecycleOptions struct {
Volumes []string
DefaultProcessType string
FileFilter func(string) bool
Workspace string
}

func NewLifecycleExecutor(logger logging.Logger, docker client.CommonAPIClient) *LifecycleExecutor {
Expand Down
10 changes: 8 additions & 2 deletions internal/build/mount_paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@ import "strings"
type mountPaths struct {
volume string
separator string
workspace string
}

func mountPathsForOS(os string) mountPaths {
func mountPathsForOS(os, workspace string) mountPaths {
if workspace == "" {
workspace = "workspace"
}
if os == "windows" {
return mountPaths{
volume: `c:`,
separator: `\`,
workspace: workspace,
}
}
return mountPaths{
volume: "",
separator: "/",
workspace: workspace,
}
}

Expand All @@ -33,7 +39,7 @@ func (m mountPaths) stackPath() string {
}

func (m mountPaths) appDirName() string {
return "workspace"
return m.workspace
}

func (m mountPaths) appDir() string {
Expand Down
3 changes: 3 additions & 0 deletions internal/commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type BuildFlags struct {
Buildpacks []string
Volumes []string
AdditionalTags []string
Workspace string
}

// Build an image from source code
Expand Down Expand Up @@ -143,6 +144,7 @@ func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cob
ProjectDescriptorBaseDir: filepath.Dir(actualDescriptorPath),
ProjectDescriptor: descriptor,
CacheImage: flags.CacheImage,
Workspace: flags.Workspace,
LifecycleImage: lifecycleImage,
}); err != nil {
return errors.Wrap(err, "failed to build")
Expand Down Expand Up @@ -181,6 +183,7 @@ This option may set DOCKER_HOST environment variable for the build container if
cmd.Flags().StringSliceVarP(&buildFlags.AdditionalTags, "tag", "t", nil, "Additional tags to push the output image to."+multiValueHelp("tag"))
cmd.Flags().BoolVar(&buildFlags.TrustBuilder, "trust-builder", false, "Trust the provided builder\nAll lifecycle phases will be run in a single container (if supported by the lifecycle).")
cmd.Flags().StringArrayVar(&buildFlags.Volumes, "volume", nil, "Mount host volume into the build container, in the form '<host path>:<target path>[:<options>]'.\n- 'host path': Name of the volume or absolute directory path to mount.\n- 'target path': The path where the file or directory is available in the container.\n- 'options' (default \"ro\"): An optional comma separated list of mount options.\n - \"ro\", volume contents are read-only.\n - \"rw\", volume contents are readable and writeable.\n - \"volume-opt=<key>=<value>\", can be specified more than once, takes a key-value pair consisting of the option name and its value."+multiValueHelp("volume"))
cmd.Flags().StringVar(&buildFlags.Workspace, "workspace", "", "Location at which to mount the app dir in the build image")
}

func validateBuildFlags(flags *BuildFlags, cfg config.Config, packClient PackClient, logger logging.Logger) error {
Expand Down

0 comments on commit bfd0c73

Please sign in to comment.