blob: b8a5442905368eb4642805ebe642a67a035e1b64 [file] [log] [blame]
// Package foundrybotrunner starts Foundry Bot to handle RBE requests and keeps it running.
package foundrybotrunner
import (
"context"
"errors"
"io/fs"
"os"
"path/filepath"
"go.skia.org/infra/go/executil"
"go.skia.org/infra/go/skerr"
"go.skia.org/infra/go/sklog"
)
// Runner is an opaque type which, once instantiated, implies a Foundry Bot binary has been found.
type Runner struct {
// path is the absolute path to a copy of Foundry Bot.
path string
}
// New constructs a fresh Foundry Bot Runner. It exists to surface errors (like Foundry Bot being
// missing) before RunUntilCancelled is called, generally on a separate goroutine.
func New() (*Runner, error) {
path, err := botPath()
if err != nil {
return nil, skerr.Wrap(err)
}
return &Runner{path: path}, nil
}
// botPath returns a path to the Foundry Bot binary sitting next to test_machine_monitor, returning
// an error if the former doesn't exist.
func botPath() (string, error) {
tmm, err := os.Executable()
if err != nil {
return "", skerr.Wrapf(err, "couldn't compute path to Foundry Bot")
}
foundryBot := filepath.Join(filepath.Dir(tmm), "bot.1")
if _, err := os.Stat(foundryBot); errors.Is(err, fs.ErrNotExist) {
return "", skerr.Wrapf(err, "Foundry Bot not found at %s", foundryBot)
}
if err != nil {
return "", skerr.Wrapf(err, "failed to stat() bot.1 in the same directory as test_machine_monitor")
}
return foundryBot, nil
}
// RunUntilCancelled runs the copy of Foundry Bot sitting next to test_machine_monitor, restarts it
// if it exits (whether successfully or with an error), and kills it if the passed-in context is
// cancelled or times out. Returns if the context comes to an end.
func (r *Runner) RunUntilCancelled(ctx context.Context) error {
for {
err := ctx.Err()
if err != nil {
return skerr.Wrapf(err, "context was cancelled or timed out")
}
cmd := executil.CommandContext(
ctx,
r.path,
"-service_address=remotebuildexecution.googleapis.com:443",
"-instance_name=projects/skia-rbe/instances/default_instance",
"session",
"-sandbox=none")
sklog.Infof("Starting %q", cmd.String())
if err := cmd.Run(); err == nil {
sklog.Errorf("Foundry Bot exited without an error, which is unexpected.")
}
}
}