Skip to content
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
File renamed without changes.
15 changes: 11 additions & 4 deletions cmd/devbox/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
)

func init() {
var noTty bool

cmd := &cobra.Command{
Use: "run <scenario>",
Short: "Run scenario defined in devbox project",
Expand Down Expand Up @@ -42,20 +44,21 @@ func init() {
args = []string{}
}

if err := runRun(ctx, p, command, args); err != nil {
if err := runRun(ctx, p, command, args, noTty); err != nil {
return fmt.Errorf("failed to run scenario: %w", err)
}

return nil
}),
}

cmd.Flags().BoolVarP(&noTty, "no-tty", "t", false, "Do not allocate a pseudo-TTY")
cmd.Flags().SetInterspersed(false)

root.AddCommand(cmd)
}

func runRun(ctx context.Context, p *project.Project, command string, args []string) error {
func runRun(ctx context.Context, p *project.Project, command string, args []string, noTtyFlag bool) error {
isRunning, err := isRunning(ctx, apiService, p)
if err != nil {
return fmt.Errorf("failed to check if services are running: %w", err)
Expand All @@ -79,9 +82,13 @@ func runRun(ctx context.Context, p *project.Project, command string, args []stri
interactive = *scenario.Interactive
}

tty := true
if scenario.Tty != nil {
var tty bool
if noTtyFlag {
tty = false
} else if scenario.Tty != nil {
tty = *scenario.Tty
} else {
tty = isTTYAvailable()
}

opts := project.RunOptions{
Expand Down
27 changes: 24 additions & 3 deletions cmd/devbox/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"os"
"strings"

"github.com/docker/docker/api/types/container"
Expand All @@ -15,6 +16,8 @@ import (
)

func init() {
var noTty bool

cmd := &cobra.Command{
Use: "shell <service>",
Short: "Run interactive shell in one of the services",
Expand All @@ -32,18 +35,20 @@ func init() {
return err
}

if err := runShell(ctx, p, args[0]); err != nil {
if err := runShell(ctx, p, args[0], noTty); err != nil {
return fmt.Errorf("failed to run shell: %w", err)
}

return nil
}),
}

cmd.Flags().BoolVarP(&noTty, "no-tty", "t", false, "Do not allocate a pseudo-TTY")

root.AddCommand(cmd)
}

func runShell(ctx context.Context, p *project.Project, serviceName string) error {
func runShell(ctx context.Context, p *project.Project, serviceName string, noTtyFlag bool) error {
_, ok := p.Services[serviceName]
if !ok {
return fmt.Errorf("service %q not found", serviceName)
Expand Down Expand Up @@ -73,10 +78,17 @@ func runShell(ctx context.Context, p *project.Project, serviceName string) error
return fmt.Errorf("failed to find a shell")
}

var tty bool
if noTtyFlag {
tty = false
} else {
tty = isTTYAvailable()
}

opts := project.RunOptions{
Service: serviceName,
Interactive: true,
Tty: true,
Tty: tty,
Command: []string{lastShell},
}

Expand Down Expand Up @@ -157,3 +169,12 @@ func filterLabels(projectName, serviceName string) filters.Args {

return filters.NewArgs(pairs...)
}

func isTTYAvailable() bool {
stat, err := os.Stdin.Stat()
if err != nil {
return false
}

return (stat.Mode() & os.ModeCharDevice) != 0
}
2 changes: 1 addition & 1 deletion internal/project/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type ScenarioConfig struct {
Description string `yaml:"description"`
Command []string `yaml:"command"`
Entrypoint []string `yaml:"entrypoint"`
Tty *bool `yaml:"tty"` // default: true
Tty *bool `yaml:"tty"` // default: auto-detect
Interactive *bool `yaml:"stdin_open"` // default: true
WorkingDir string `yaml:"working_dir"`
User string `yaml:"user"`
Expand Down