-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Run takes a DetectFunc and a BuildFunc as arguments. Then when compiled into executables called "detect" or "build", it uses the name of the executable to determine which phase to run. This helps simplify buildpacks wishing to combine their detect and build executables into a single executable with symlinking.
- Loading branch information
1 parent
89bf78c
commit d96d141
Showing
5 changed files
with
225 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package packit | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/paketo-buildpacks/packit/internal" | ||
) | ||
|
||
// Run combines the invocation of both build and detect into a single entry | ||
// point. Calling Run from an executable with a name matching "build" or | ||
// "detect" will result in the matching DetectFunc or BuildFunc being called. | ||
func Run(detect DetectFunc, build BuildFunc, options ...Option) { | ||
config := OptionConfig{ | ||
exitHandler: internal.NewExitHandler(), | ||
args: os.Args, | ||
} | ||
|
||
for _, option := range options { | ||
config = option(config) | ||
} | ||
|
||
phase := filepath.Base(config.args[0]) | ||
|
||
switch phase { | ||
case "detect": | ||
Detect(detect, options...) | ||
|
||
case "build": | ||
Build(build, options...) | ||
|
||
default: | ||
config.exitHandler.Error(fmt.Errorf("failed to run buildpack: unknown lifecycle phase %q", phase)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
package packit_test | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/paketo-buildpacks/packit" | ||
"github.com/paketo-buildpacks/packit/fakes" | ||
"github.com/sclevine/spec" | ||
|
||
. "github.com/onsi/gomega" | ||
) | ||
|
||
func testRun(t *testing.T, context spec.G, it spec.S) { | ||
var ( | ||
Expect = NewWithT(t).Expect | ||
|
||
workingDir string | ||
tmpDir string | ||
cnbDir string | ||
exitHandler *fakes.ExitHandler | ||
) | ||
|
||
it.Before(func() { | ||
var err error | ||
workingDir, err = os.Getwd() | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
tmpDir, err = ioutil.TempDir("", "") | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
tmpDir, err = filepath.EvalSymlinks(tmpDir) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
Expect(os.Chdir(tmpDir)).To(Succeed()) | ||
|
||
cnbDir, err = ioutil.TempDir("", "cnb") | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
Expect(ioutil.WriteFile(filepath.Join(cnbDir, "buildpack.toml"), []byte(` | ||
[buildpack] | ||
id = "some-id" | ||
name = "some-name" | ||
version = "some-version" | ||
clear-env = false | ||
`), 0644)).To(Succeed()) | ||
|
||
exitHandler = &fakes.ExitHandler{} | ||
}) | ||
|
||
it.After(func() { | ||
Expect(os.Chdir(workingDir)).To(Succeed()) | ||
Expect(os.RemoveAll(tmpDir)).To(Succeed()) | ||
Expect(os.RemoveAll(cnbDir)).To(Succeed()) | ||
}) | ||
|
||
context("when running the detect executable", func() { | ||
var ( | ||
args []string | ||
buildPlanPath string | ||
) | ||
|
||
it.Before(func() { | ||
buildPlanPath = filepath.Join(tmpDir, "buildplan.toml") | ||
|
||
args = []string{filepath.Join(cnbDir, "bin", "detect"), "", buildPlanPath} | ||
}) | ||
|
||
it.After(func() { | ||
Expect(os.Remove(buildPlanPath)).To(Succeed()) | ||
}) | ||
|
||
it("calls the DetectFunc", func() { | ||
var detectCalled bool | ||
|
||
detect := func(packit.DetectContext) (packit.DetectResult, error) { | ||
detectCalled = true | ||
return packit.DetectResult{}, nil | ||
} | ||
|
||
packit.Run(detect, nil, packit.WithArgs(args), packit.WithExitHandler(exitHandler)) | ||
|
||
Expect(detectCalled).To(BeTrue()) | ||
Expect(exitHandler.ErrorCall.CallCount).To(Equal(0)) | ||
}) | ||
}) | ||
|
||
context("when running the build executable", func() { | ||
var ( | ||
args []string | ||
layersDir string | ||
planPath string | ||
) | ||
|
||
it.Before(func() { | ||
file, err := ioutil.TempFile("", "plan.toml") | ||
Expect(err).NotTo(HaveOccurred()) | ||
defer file.Close() | ||
|
||
_, err = file.WriteString(` | ||
[[entries]] | ||
name = "some-entry" | ||
version = "some-version" | ||
[entries.metadata] | ||
some-key = "some-value" | ||
`) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
planPath = file.Name() | ||
|
||
layersDir, err = ioutil.TempDir("", "layers") | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
args = []string{filepath.Join(cnbDir, "bin", "build"), layersDir, "", planPath} | ||
}) | ||
|
||
it.After(func() { | ||
Expect(os.RemoveAll(layersDir)).To(Succeed()) | ||
Expect(os.Remove(planPath)).To(Succeed()) | ||
}) | ||
|
||
it("calls the BuildFunc", func() { | ||
var buildCalled bool | ||
|
||
build := func(packit.BuildContext) (packit.BuildResult, error) { | ||
buildCalled = true | ||
return packit.BuildResult{}, nil | ||
} | ||
|
||
packit.Run(nil, build, packit.WithArgs(args), packit.WithExitHandler(exitHandler)) | ||
|
||
Expect(buildCalled).To(BeTrue()) | ||
Expect(exitHandler.ErrorCall.CallCount).To(Equal(0)) | ||
}) | ||
}) | ||
|
||
context("when running any other executable", func() { | ||
var args []string | ||
|
||
it.Before(func() { | ||
args = []string{filepath.Join(cnbDir, "bin", "something-else"), "some", "args"} | ||
}) | ||
|
||
it("returns an error", func() { | ||
packit.Run(nil, nil, packit.WithArgs(args), packit.WithExitHandler(exitHandler)) | ||
|
||
Expect(exitHandler.ErrorCall.Receives.Error).To(MatchError("failed to run buildpack: unknown lifecycle phase \"something-else\"")) | ||
}) | ||
}) | ||
} |