Skip to content

Commit

Permalink
core: pass context.Context to the command runner to adhere to timeo…
Browse files Browse the repository at this point in the history
…uts, if set (#134)
  • Loading branch information
mohammed90 authored Mar 3, 2023
1 parent 421d60b commit 5d0f23f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 24 deletions.
13 changes: 9 additions & 4 deletions builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ type Builder struct {
// Build builds Caddy at the configured version with the
// configured plugins and plops down a binary at outputFile.
func (b Builder) Build(ctx context.Context, outputFile string) error {
var cancel context.CancelFunc
if b.TimeoutBuild > 0 {
ctx, cancel = context.WithTimeout(ctx, b.TimeoutBuild)
defer cancel()
}
if outputFile == "" {
return fmt.Errorf("output file path is required")
}
Expand Down Expand Up @@ -102,13 +107,13 @@ func (b Builder) Build(ctx context.Context, outputFile string) error {
log.Println("[INFO] Building Caddy")

// tidy the module to ensure go.mod and go.sum are consistent with the module prereq
tidyCmd := buildEnv.newGoModCommand("tidy")
if err := buildEnv.runCommand(ctx, tidyCmd, b.TimeoutGet); err != nil {
tidyCmd := buildEnv.newGoModCommand(ctx, "tidy")
if err := buildEnv.runCommand(ctx, tidyCmd); err != nil {
return err
}

// compile
cmd := buildEnv.newGoBuildCommand("build",
cmd := buildEnv.newGoBuildCommand(ctx, "build",
"-o", absOutputFile,
)
if b.Debug {
Expand All @@ -127,7 +132,7 @@ func (b Builder) Build(ctx context.Context, outputFile string) error {
cmd.Args = append(cmd.Args, "-race")
}
cmd.Env = env
err = buildEnv.runCommand(ctx, cmd, b.TimeoutBuild)
err = buildEnv.runCommand(ctx, cmd)
if err != nil {
return err
}
Expand Down
43 changes: 23 additions & 20 deletions environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ func (b Builder) newEnvironment(ctx context.Context) (*environment, error) {

// initialize the go module
log.Println("[INFO] Initializing Go module")
cmd := env.newGoModCommand("init")
cmd := env.newGoModCommand(ctx, "init")
cmd.Args = append(cmd.Args, "caddy")
err = env.runCommand(ctx, cmd, 10*time.Second)
err = env.runCommand(ctx, cmd)
if err != nil {
return nil, err
}
Expand All @@ -115,9 +115,9 @@ func (b Builder) newEnvironment(ctx context.Context) (*environment, error) {
replaced := make(map[string]string)
for _, r := range b.Replacements {
log.Printf("[INFO] Replace %s => %s", r.Old.String(), r.New.String())
cmd := env.newGoModCommand("edit",
cmd := env.newGoModCommand(ctx, "edit",
"-replace", fmt.Sprintf("%s=%s", r.Old.Param(), r.New.Param()))
err := env.runCommand(ctx, cmd, 10*time.Second)
err := env.runCommand(ctx, cmd)
if err != nil {
return nil, err
}
Expand All @@ -131,6 +131,14 @@ func (b Builder) newEnvironment(ctx context.Context) (*environment, error) {
default:
}

// The timeout for the `go get` command may be different than `go build`,
// so create a new context with the timeout for `go get`
if env.timeoutGoGet > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(context.Background(), env.timeoutGoGet)
defer cancel()
}

// pin versions by populating go.mod, first for Caddy itself and then plugins
log.Println("[INFO] Pinning versions")
err = env.execGoGet(ctx, caddyModulePath, env.caddyVersion, "", "")
Expand Down Expand Up @@ -195,8 +203,8 @@ func (env environment) Close() error {
return os.RemoveAll(env.tempFolder)
}

func (env environment) newCommand(command string, args ...string) *exec.Cmd {
cmd := exec.Command(command, args...)
func (env environment) newCommand(ctx context.Context, command string, args ...string) *exec.Cmd {
cmd := exec.CommandContext(ctx, command, args...)
cmd.Dir = env.tempFolder
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Expand All @@ -205,16 +213,16 @@ func (env environment) newCommand(command string, args ...string) *exec.Cmd {

// newGoBuildCommand creates a new *exec.Cmd which assumes the first element in `args` is one of: build, clean, get, install, list, run, or test. The
// created command will also have the value of `XCADDY_GO_BUILD_FLAGS` appended to its arguments, if set.
func (env environment) newGoBuildCommand(args ...string) *exec.Cmd {
cmd := env.newCommand(utils.GetGo(), args...)
func (env environment) newGoBuildCommand(ctx context.Context, args ...string) *exec.Cmd {
cmd := env.newCommand(ctx, utils.GetGo(), args...)
return parseAndAppendFlags(cmd, env.buildFlags)
}

// newGoModCommand creates a new *exec.Cmd which assumes `args` are the args for `go mod` command. The
// created command will also have the value of `XCADDY_GO_MOD_FLAGS` appended to its arguments, if set.
func (env environment) newGoModCommand(args ...string) *exec.Cmd {
func (env environment) newGoModCommand(ctx context.Context, args ...string) *exec.Cmd {
args = append([]string{"mod"}, args...)
cmd := env.newCommand(utils.GetGo(), args...)
cmd := env.newCommand(ctx, utils.GetGo(), args...)
return parseAndAppendFlags(cmd, env.modFlags)
}

Expand All @@ -233,14 +241,9 @@ func parseAndAppendFlags(cmd *exec.Cmd, flags string) *exec.Cmd {
return cmd
}

func (env environment) runCommand(ctx context.Context, cmd *exec.Cmd, timeout time.Duration) error {
log.Printf("[INFO] exec (timeout=%s): %+v ", timeout, cmd)

if timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}
func (env environment) runCommand(ctx context.Context, cmd *exec.Cmd) error {
deadline, _ := ctx.Deadline()
log.Printf("[INFO] exec (timeout=%s): %+v ", time.Until(deadline), cmd)

// start the command; if it fails to start, report error immediately
err := cmd.Start()
Expand Down Expand Up @@ -295,7 +298,7 @@ func (env environment) execGoGet(ctx context.Context, modulePath, moduleVersion,
caddy += "@" + caddyVersion
}

cmd := env.newGoBuildCommand("get", "-d", "-v")
cmd := env.newGoBuildCommand(ctx, "get", "-d", "-v")
// using an empty string as an additional argument to "go get"
// breaks the command since it treats the empty string as a
// distinct argument, so we're using an if statement to avoid it.
Expand All @@ -305,7 +308,7 @@ func (env environment) execGoGet(ctx context.Context, modulePath, moduleVersion,
cmd.Args = append(cmd.Args, mod)
}

return env.runCommand(ctx, cmd, env.timeoutGoGet)
return env.runCommand(ctx, cmd)
}

type goModTemplateContext struct {
Expand Down

0 comments on commit 5d0f23f

Please sign in to comment.