Skip to content

Commit

Permalink
fix pack logger blocking stderr writes
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeldwan committed Mar 26, 2021
1 parent c61c9f7 commit 2d76a47
Showing 1 changed file with 47 additions and 6 deletions.
53 changes: 47 additions & 6 deletions internal/build/imgsrc/buildpacks_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"os"

"github.com/buildpacks/pack"
"github.com/superfly/flyctl/flyctl"
Expand Down Expand Up @@ -39,7 +40,7 @@ func (s *buildpacksStrategy) Run(ctx context.Context, dockerFactory *dockerClien

defer clearDeploymentTags(ctx, docker, opts.Tag)

packClient, err := pack.NewClient(pack.WithDockerClient(docker), pack.WithLogger(&packLogger{w: streams.Out, debug: false}))
packClient, err := pack.NewClient(pack.WithDockerClient(docker), pack.WithLogger(newPackLogger(streams.Out)))
if err != nil {
return nil, err
}
Expand All @@ -53,7 +54,6 @@ func (s *buildpacksStrategy) Run(ctx context.Context, dockerFactory *dockerClien
Buildpacks: buildpacks,
Env: normalizeBuildArgs(opts.AppConfig, opts.ExtraBuildArgs),
TrustBuilder: true,
// Publish: opts.Publish,
})

if err != nil {
Expand Down Expand Up @@ -100,6 +100,26 @@ func normalizeBuildArgs(appConfig *flyctl.AppConfig, extra map[string]string) ma
return out
}

func newPackLogger(out io.Writer) *packLogger {
// pack blocks writes to the underlying writer for it's lifetime.
// we need to use it too, so instead of giving pack stdout/stderr
// give it a burner writer that we pipe to the target
packR, packW := io.Pipe()

go func() {
io.Copy(out, packR)
defer packR.Close()
}()

return &packLogger{
w: &fdWrapper{
Writer: packW,
src: out,
},
debug: os.Getenv("LOG_LEVEL") == "debug",
}
}

type packLogger struct {
w io.Writer
debug bool
Expand All @@ -116,31 +136,31 @@ func (l *packLogger) Debugf(format string, v ...interface{}) {
if !l.debug {
return
}
fmt.Fprintf(l.w, cmdfmt.AppendMissingLineFeed(fmt.Sprintf(format, v...)))
fmt.Fprint(l.w, cmdfmt.AppendMissingLineFeed(fmt.Sprintf(format, v...)))
}

func (l *packLogger) Info(msg string) {
fmt.Fprint(l.w, cmdfmt.AppendMissingLineFeed(msg))
}

func (l *packLogger) Infof(format string, v ...interface{}) {
fmt.Fprintf(l.w, cmdfmt.AppendMissingLineFeed(fmt.Sprintf(format, v...)))
fmt.Fprint(l.w, cmdfmt.AppendMissingLineFeed(fmt.Sprintf(format, v...)))
}

func (l *packLogger) Warn(msg string) {
fmt.Fprint(l.w, cmdfmt.AppendMissingLineFeed(msg))
}

func (l *packLogger) Warnf(format string, v ...interface{}) {
fmt.Fprintf(l.w, cmdfmt.AppendMissingLineFeed(fmt.Sprintf(format, v...)))
fmt.Fprint(l.w, cmdfmt.AppendMissingLineFeed(fmt.Sprintf(format, v...)))
}

func (l *packLogger) Error(msg string) {
fmt.Fprint(l.w, cmdfmt.AppendMissingLineFeed(msg))
}

func (l *packLogger) Errorf(format string, v ...interface{}) {
fmt.Fprintf(l.w, cmdfmt.AppendMissingLineFeed(fmt.Sprintf(format, v...)))
fmt.Fprint(l.w, cmdfmt.AppendMissingLineFeed(fmt.Sprintf(format, v...)))
}

func (l *packLogger) Writer() io.Writer {
Expand All @@ -150,3 +170,24 @@ func (l *packLogger) Writer() io.Writer {
func (l *packLogger) IsVerbose() bool {
return l.debug
}

// fdWrapper creates an io.Writer wrapper that writes to one Writer but reads Fd from another.
// this is used so we can pass the correct Fd through for terminal detection while
// still writing to our piped writer
type fdWrapper struct {
io.Writer

src io.Writer
}

type fdWriter interface {
Fd() uintptr
}

func (w *fdWrapper) Fd() uintptr {
fmt.Println("get fd", w.src, w.Writer)
if fd, ok := w.src.(fdWriter); ok {
return fd.Fd()
}
return ^(uintptr(0))
}

0 comments on commit 2d76a47

Please sign in to comment.