Skip to content

Commit

Permalink
wip: Show detect screen during detect phase
Browse files Browse the repository at this point in the history
Signed-off-by: Anthony Emengo <aemengo@vmware.com>
  • Loading branch information
Anthony Emengo committed Jul 26, 2021
1 parent 66a4f32 commit 55f34f3
Show file tree
Hide file tree
Showing 16 changed files with 362 additions and 1 deletion.
4 changes: 4 additions & 0 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ type BuildOptions struct {

// User's group id used to build the image
GroupID int

// TODO: put words
Interactive bool
}

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

lifecycleVersion := ephemeralBuilder.LifecycleDescriptor().Info.Version
Expand Down
74 changes: 74 additions & 0 deletions cmd/pack-agent/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package main

import (
"bufio"
"encoding/json"
"fmt"
"github.com/buildpacks/pack/internal/screen"
"io"
"os"
"os/exec"
"strings"
)

func main() {
command := exec.Command(os.Args[1], os.Args[2:]...)

reader, err := start(command)
if err != nil {
panic(err)
}

err = command.Start()
if err != nil {
panic(err)
}

err = handleOutput(reader)

err = command.Wait()
if err != nil {
panic(err)
}

log(screen.NewEvent("EXPORT", "Ending"))
os.Exit(command.ProcessState.ExitCode())
}

func log(evt screen.Event) {
data, _ := json.Marshal(evt)
fmt.Println(string(data))
}

func handleOutput(reader io.Reader) error {
scanner := bufio.NewScanner(reader)

for scanner.Scan() {
text := scanner.Text()

switch {
case strings.Contains(text, "===> DETECTING"):
log(screen.NewEvent("DETECT", "Starting"))
case strings.Contains(text, "===> ANALYZING"):
log(screen.NewEvent("DETECT", "Ending"))
log(screen.NewEvent("ANALYZE", "Starting"))
}
}

return scanner.Err()
}

func start(command *exec.Cmd) (io.Reader, error) {
stdout, err := command.StdoutPipe()
if err != nil {
return nil, err
}

stderr, err := command.StderrPipe()
if err != nil {
return nil, err
}

reader := io.MultiReader(stdout, stderr)
return reader, nil
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41 // indirect
github.com/docker/docker v20.10.7+incompatible
github.com/docker/go-connections v0.4.0
github.com/gdamore/tcell/v2 v2.3.3 // indirect
github.com/ghodss/yaml v1.0.0
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.5.6
Expand All @@ -27,6 +28,7 @@ require (
github.com/opencontainers/selinux v1.6.0 // indirect
github.com/pelletier/go-toml v1.9.3
github.com/pkg/errors v0.9.1
github.com/rivo/tview v0.0.0-20210624165335-29d673af0ce2 // indirect
github.com/sabhiram/go-gitignore v0.0.0-20201211074657-223ce5d391b0
github.com/sclevine/spec v1.4.0
github.com/sergi/go-diff v1.1.0 // indirect
Expand Down
18 changes: 18 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell/v2 v2.3.3 h1:RKoI6OcqYrr/Do8yHZklecdGzDTJH9ACKdfECbRdw3M=
github.com/gdamore/tcell/v2 v2.3.3/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
Expand Down Expand Up @@ -341,6 +345,9 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
Expand All @@ -357,6 +364,8 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
Expand Down Expand Up @@ -446,6 +455,11 @@ github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rivo/tview v0.0.0-20210624165335-29d673af0ce2 h1:I5N0WNMgPSq5NKUFspB4jMJ6n2P0ipz5FlOlB4BXviQ=
github.com/rivo/tview v0.0.0-20210624165335-29d673af0ce2/go.mod h1:IxQujbYMAh4trWr0Dwa8jfciForjVmxyHpskZX6aydQ=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
Expand Down Expand Up @@ -726,6 +740,7 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -734,6 +749,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
13 changes: 13 additions & 0 deletions internal/build/lifecycle_execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/buildpacks/pack/internal/builder"
"github.com/buildpacks/pack/internal/cache"
"github.com/buildpacks/pack/internal/paths"
"github.com/buildpacks/pack/internal/screen"
"github.com/buildpacks/pack/internal/style"
"github.com/buildpacks/pack/logging"
)
Expand All @@ -34,6 +35,7 @@ type LifecycleExecution struct {
os string
mountPaths mountPaths
opts LifecycleOptions
screen *screen.Screen
}

func NewLifecycleExecution(logger logging.Logger, docker client.CommonAPIClient, opts LifecycleOptions) (*LifecycleExecution, error) {
Expand All @@ -59,6 +61,7 @@ func NewLifecycleExecution(logger logging.Logger, docker client.CommonAPIClient,
opts: opts,
os: osType,
mountPaths: mountPathsForOS(osType, opts.Workspace),
screen: screen.NewScreen(),
}

return exec, nil
Expand Down Expand Up @@ -131,6 +134,11 @@ func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseF

launchCache := cache.NewVolumeCache(l.opts.Image, "launch", l.docker)

if l.opts.Interactive {
//TODO: want this on the main thread
go l.screen.Run()
}

if !l.opts.UseCreator {
l.logger.Info(style.Step("DETECTING"))
if err := l.Detect(ctx, l.opts.Network, l.opts.Volumes, phaseFactory); err != nil {
Expand Down Expand Up @@ -227,6 +235,11 @@ func (l *LifecycleExecution) Create(ctx context.Context, publish bool, dockerHos

create := phaseFactory.New(NewPhaseConfigProvider("creator", l, opts...))
defer create.Cleanup()
defer func() {
if l.opts.Interactive {
l.screen.Start()
}
}()
return create.Run(ctx)
}

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 @@ -72,6 +72,7 @@ type LifecycleOptions struct {
FileFilter func(string) bool
Workspace string
GID int
Interactive bool
}

func NewLifecycleExecutor(logger logging.Logger, docker client.CommonAPIClient) *LifecycleExecutor {
Expand Down
7 changes: 7 additions & 0 deletions internal/build/phase_config_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ func NewPhaseConfigProvider(name string, lifecycleExec *LifecycleExecution, ops
lifecycleExec.logger.Debug("Host Settings:")
lifecycleExec.logger.Debugf(" Binds: %s", style.Symbol(strings.Join(provider.hostConf.Binds, " ")))
lifecycleExec.logger.Debugf(" Network Mode: %s", style.Symbol(string(provider.hostConf.NetworkMode)))

if lifecycleExec.opts.Interactive {
provider.ctrConf.Cmd = append([]string{"/cnb/pack-agent/pack-agent"}, provider.ctrConf.Cmd...)
provider.infoWriter = lifecycleExec.screen.Writer()
provider.errorWriter = lifecycleExec.screen.Writer()
}

return provider
}

Expand Down
26 changes: 25 additions & 1 deletion internal/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const (

orderPath = "/cnb/order.toml"
stackPath = "/cnb/stack.toml"
agentPath = "/cnb/pack-agent/pack-agent"
platformDir = "/platform"
lifecycleDir = "/cnb/lifecycle"
compatLifecycleDir = "/lifecycle"
Expand Down Expand Up @@ -331,6 +332,14 @@ func (b *Builder) Save(logger logging.Logger, creatorMetadata CreatorMetadata) e
}
}

agentTar, err := b.agentLayer(tmpDir)
if err != nil {
return err
}
if err := b.image.AddLayer(agentTar); err != nil {
return errors.Wrapf(err, "adding pack-agent.tar layer")
}

stackTar, err := b.stackLayer(tmpDir)
if err != nil {
return err
Expand Down Expand Up @@ -606,7 +615,7 @@ func (b *Builder) defaultDirsLayer(dest string) (string, error) {
}

// can't use filepath.Join(), to ensure Windows doesn't transform it to Windows join
for _, path := range []string{cnbDir, dist.BuildpacksDir, platformDir, platformDir + "/env"} {
for _, path := range []string{cnbDir, dist.BuildpacksDir, dist.PackAgentDir, platformDir, platformDir + "/env"} {
if err := lw.WriteHeader(b.rootOwnedDir(path, ts)); err != nil {
return "", errors.Wrapf(err, "creating %s dir in layer", style.Symbol(path))
}
Expand Down Expand Up @@ -740,6 +749,21 @@ func orderFileContents(order dist.Order) (string, error) {
return buf.String(), nil
}

func (b *Builder) agentLayer(dest string) (string, error) {
contents, err := ioutil.ReadFile("/tmp/pack-agent")
if err != nil {
return "", errors.Wrapf(err, "failed to read pack-agent")
}

layerTar := filepath.Join(dest, "pack-agent.tar")
err = layer.CreateSingleExeTar(layerTar, agentPath, contents, b.layerWriterFactory)
if err != nil {
return "", errors.Wrapf(err, "failed to create pack-agent layer tar")
}

return layerTar, nil
}

func (b *Builder) stackLayer(dest string) (string, error) {
buf := &bytes.Buffer{}
err := toml.NewEncoder(buf).Encode(b.metadata.Stack)
Expand Down
8 changes: 8 additions & 0 deletions internal/commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type BuildFlags struct {
AdditionalTags []string
Workspace string
GID int
Interactive bool
}

// Build an image from source code
Expand Down Expand Up @@ -152,6 +153,7 @@ func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cob
Workspace: flags.Workspace,
LifecycleImage: lifecycleImage,
GroupID: gid,
Interactive: flags.Interactive,
}); err != nil {
return errors.Wrap(err, "failed to build")
}
Expand Down Expand Up @@ -191,6 +193,7 @@ This option may set DOCKER_HOST environment variable for the build container if
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")
cmd.Flags().IntVar(&buildFlags.GID, "gid", 0, `Override GID of user's group in the stack's build and run images. The provided value must be a positive number`)
cmd.Flags().BoolVarP(&buildFlags.Interactive, "interactive", "i", false, "Perform builds step-by-step with a terminal UI")
}

func validateBuildFlags(flags *BuildFlags, cfg config.Config, packClient PackClient, logger logging.Logger) error {
Expand All @@ -205,6 +208,11 @@ func validateBuildFlags(flags *BuildFlags, cfg config.Config, packClient PackCli
if flags.GID < 0 {
return errors.New("gid flag must be in the range of 0-2147483647")
}

if flags.Interactive && !cfg.Experimental {
return pack.NewExperimentError("Interactive mode is currently experimental.")
}

return nil
}

Expand Down
1 change: 1 addition & 0 deletions internal/dist/buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

const AssumedBuildpackAPIVersion = "0.1"
const BuildpacksDir = "/cnb/buildpacks"
const PackAgentDir = "/cnb/pack-agent"

type Blob interface {
// Open returns a io.ReadCloser for the contents of the Blob in tar format.
Expand Down
6 changes: 6 additions & 0 deletions internal/layer/layer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ func CreateSingleFileTar(tarFile, path, txt string, twf archive.TarWriterFactory
tarBuilder.AddFile(path, 0644, archive.NormalizedDateTime, []byte(txt))
return tarBuilder.WriteToPath(tarFile, twf)
}

func CreateSingleExeTar(tarFile, path string, contents []byte, twf archive.TarWriterFactory) error {
tarBuilder := archive.TarBuilder{}
tarBuilder.AddFile(path, 0777, archive.NormalizedDateTime, contents)
return tarBuilder.WriteToPath(tarFile, twf)
}
29 changes: 29 additions & 0 deletions internal/screen/blank.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package screen

import "github.com/rivo/tview"

type Blank struct {
app *tview.Application
textView *tview.TextView
doneChan chan bool
}

func NewBlank(app *tview.Application) *Blank {
return &Blank{
app: app,
doneChan: make(chan bool, 1),
}
}

func (d *Blank) Start() {
box := tview.NewBox()
box.SetBackgroundColor(backgroundColor)

flex := tview.NewFlex()
flex.AddItem(box, 0, 1, false)
d.app.SetRoot(flex, true)
}

func (d *Blank) Stop() {
// no-op
}
Loading

0 comments on commit 55f34f3

Please sign in to comment.