Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a process entry for all of the binaries #142

Merged
merged 3 commits into from
Feb 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions build.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package gobuild

import (
"errors"
"path/filepath"
"time"

"github.com/paketo-buildpacks/packit"
"github.com/paketo-buildpacks/packit/chronos"
"github.com/paketo-buildpacks/packit/scribe"
)

//go:generate faux --interface BuildProcess --output fakes/build_process.go
type BuildProcess interface {
Execute(config GoBuildConfiguration) (command string, err error)
Execute(config GoBuildConfiguration) (binaries []string, err error)
}

//go:generate faux --interface PathManager --output fakes/path_manager.go
Expand All @@ -31,7 +29,7 @@ func Build(
buildProcess BuildProcess,
pathManager PathManager,
clock chronos.Clock,
logs scribe.Emitter,
logs LogEmitter,
sourceRemover SourceRemover,
) packit.BuildFunc {

Expand Down Expand Up @@ -64,7 +62,7 @@ func Build(
return packit.BuildResult{}, err
}

command, err := buildProcess.Execute(GoBuildConfiguration{
binaries, err := buildProcess.Execute(GoBuildConfiguration{
Workspace: path,
Output: filepath.Join(targetsLayer.Path, "bin"),
GoPath: goPath,
Expand All @@ -83,32 +81,36 @@ func Build(

targetsLayer.Metadata = map[string]interface{}{
"built_at": clock.Now().Format(time.RFC3339Nano),
"command": command,
}

command, ok := targetsLayer.Metadata["command"].(string)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ForestEckhardt do you know why this code existed before or when you could ever get into the failure case where command would not be defined as a string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use to reuse the binary layer from cache if nothing changed workspace directory. We no longer do that and always rebuild from source. This was metadata that we used to rewrite the start command on a rebuild where we reused the binary layer. That functionality has been removed so this is just dead code.

if !ok {
return packit.BuildResult{}, errors.New("failed to identify start command from reused layer metadata")
}

err = sourceRemover.Clear(context.WorkingDir)
if err != nil {
return packit.BuildResult{}, err
}

processes := []packit.Process{
{
Type: "web",
Command: binaries[0],
Direct: context.Stack == TinyStackName,
},
}

for _, binary := range binaries {
processes = append(processes, packit.Process{
Type: filepath.Base(binary),
Command: binary,
Direct: context.Stack == TinyStackName,
})
}

logs.Process("Assigning launch processes")
logs.Subprocess("web: %s", command)
logs.ListProcesses(processes)

return packit.BuildResult{
Layers: []packit.Layer{targetsLayer, goCacheLayer},
Launch: packit.LaunchMetadata{
Processes: []packit.Process{
{
Type: "web",
Command: command,
Direct: context.Stack == TinyStackName,
},
},
Processes: processes,
},
}, nil
}
Expand Down
35 changes: 27 additions & 8 deletions build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/paketo-buildpacks/go-build/fakes"
"github.com/paketo-buildpacks/packit"
"github.com/paketo-buildpacks/packit/chronos"
"github.com/paketo-buildpacks/packit/scribe"
"github.com/sclevine/spec"

. "github.com/onsi/gomega"
Expand Down Expand Up @@ -49,7 +48,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Expect(err).NotTo(HaveOccurred())

buildProcess = &fakes.BuildProcess{}
buildProcess.ExecuteCall.Returns.Command = "some-start-command"
buildProcess.ExecuteCall.Returns.Binaries = []string{"path/some-start-command", "path/another-start-command"}

pathManager = &fakes.PathManager{}
pathManager.SetupCall.Returns.GoPath = "some-go-path"
Expand All @@ -76,7 +75,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
buildProcess,
pathManager,
clock,
scribe.NewEmitter(logs),
gobuild.NewLogEmitter(logs),
sourceRemover,
)
})
Expand Down Expand Up @@ -113,7 +112,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Cache: false,
Metadata: map[string]interface{}{
"built_at": timestamp.Format(time.RFC3339Nano),
"command": "some-start-command",
},
},
{
Expand All @@ -131,7 +129,17 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Processes: []packit.Process{
{
Type: "web",
Command: "some-start-command",
Command: "path/some-start-command",
Direct: false,
},
{
Type: "some-start-command",
Command: "path/some-start-command",
Direct: false,
},
{
Type: "another-start-command",
Command: "path/another-start-command",
Direct: false,
},
},
Expand Down Expand Up @@ -159,7 +167,9 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {

Expect(logs.String()).To(ContainSubstring("Some Buildpack some-version"))
Expect(logs.String()).To(ContainSubstring("Assigning launch processes"))
Expect(logs.String()).To(ContainSubstring("web: some-start-command"))
Expect(logs.String()).To(ContainSubstring("web: path/some-start-command"))
Expect(logs.String()).To(ContainSubstring("some-start-command: path/some-start-command"))
Expect(logs.String()).To(ContainSubstring("another-start-command: path/another-start-command"))
})

context("when the stack is tiny", func() {
Expand Down Expand Up @@ -189,7 +199,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Cache: false,
Metadata: map[string]interface{}{
"built_at": timestamp.Format(time.RFC3339Nano),
"command": "some-start-command",
},
},
{
Expand All @@ -207,7 +216,17 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Processes: []packit.Process{
{
Type: "web",
Command: "some-start-command",
Command: "path/some-start-command",
Direct: true,
},
{
Type: "some-start-command",
Command: "path/some-start-command",
Direct: true,
},
{
Type: "another-start-command",
Command: "path/another-start-command",
Direct: true,
},
},
Expand Down
10 changes: 5 additions & 5 deletions fakes/build_process.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ type BuildProcess struct {
Config gobuild.GoBuildConfiguration
}
Returns struct {
Command string
Err error
Binaries []string
Err error
}
Stub func(gobuild.GoBuildConfiguration) (string, error)
Stub func(gobuild.GoBuildConfiguration) ([]string, error)
}
}

func (f *BuildProcess) Execute(param1 gobuild.GoBuildConfiguration) (string, error) {
func (f *BuildProcess) Execute(param1 gobuild.GoBuildConfiguration) ([]string, error) {
f.ExecuteCall.Lock()
defer f.ExecuteCall.Unlock()
f.ExecuteCall.CallCount++
f.ExecuteCall.Receives.Config = param1
if f.ExecuteCall.Stub != nil {
return f.ExecuteCall.Stub(param1)
}
return f.ExecuteCall.Returns.Command, f.ExecuteCall.Returns.Err
return f.ExecuteCall.Returns.Binaries, f.ExecuteCall.Returns.Err
}
44 changes: 33 additions & 11 deletions go_build_process.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gobuild

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"os"
Expand All @@ -13,7 +14,6 @@ import (

"github.com/paketo-buildpacks/packit/chronos"
"github.com/paketo-buildpacks/packit/pexec"
"github.com/paketo-buildpacks/packit/scribe"
)

//go:generate faux --interface Executable --output fakes/executable.go
Expand All @@ -32,24 +32,24 @@ type GoBuildConfiguration struct {

type GoBuildProcess struct {
executable Executable
logs scribe.Emitter
logs LogEmitter
clock chronos.Clock
}

func NewGoBuildProcess(executable Executable, logs scribe.Emitter, clock chronos.Clock) GoBuildProcess {
func NewGoBuildProcess(executable Executable, logs LogEmitter, clock chronos.Clock) GoBuildProcess {
return GoBuildProcess{
executable: executable,
logs: logs,
clock: clock,
}
}

func (p GoBuildProcess) Execute(config GoBuildConfiguration) (string, error) {
func (p GoBuildProcess) Execute(config GoBuildConfiguration) ([]string, error) {
p.logs.Process("Executing build process")

err := os.MkdirAll(config.Output, os.ModePerm)
if err != nil {
return "", fmt.Errorf("failed to create targets output directory: %w", err)
return nil, fmt.Errorf("failed to create targets output directory: %w", err)
}

contains := func(flags []string, match string) bool {
Expand Down Expand Up @@ -94,22 +94,44 @@ func (p GoBuildProcess) Execute(config GoBuildConfiguration) (string, error) {
p.logs.Action("Failed after %s", duration.Round(time.Millisecond))
p.logs.Detail(buffer.String())

return "", fmt.Errorf("failed to execute 'go build': %w", err)
return nil, fmt.Errorf("failed to execute 'go build': %w", err)
}

p.logs.Action("Completed in %s", duration.Round(time.Millisecond))
p.logs.Break()

paths, err := filepath.Glob(fmt.Sprintf("%s/*", config.Output))
if err != nil {
return "", fmt.Errorf("failed to list targets: %w", err)
var paths []string
for _, target := range config.Targets {
buffer = bytes.NewBuffer(nil)
err := p.executable.Execute(pexec.Execution{
Args: []string{"list", "--json", target},
Dir: config.Workspace,
Env: env,
Stdout: buffer,
Stderr: buffer,
})
if err != nil {
p.logs.Detail(buffer.String())

return nil, fmt.Errorf("failed to execute 'go list': %w", err)
}

var list struct {
ImportPath string `json:"ImportPath"`
}
err = json.Unmarshal(buffer.Bytes(), &list)
if err != nil {
return nil, fmt.Errorf("failed to parse 'go list' output: %w", err)
}

paths = append(paths, filepath.Join(config.Output, filepath.Base(list.ImportPath)))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small optional microoptimization: Since the length of paths will be the length of config.Target, you can initialize path with a length of len(config.Targets and use path[i] = filepath.Join(config.Output, filepath.Base(list.ImportPath)) rather than append (which might have to grow).

}

if len(paths) == 0 {
return "", errors.New("failed to determine go executable start command")
return nil, errors.New("failed to determine go executable start command")
}

return paths[0], nil
return paths, nil
}

func formatArg(arg string) string {
Expand Down
Loading