| // Copyright 2023 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| package main |
| |
| import ( |
| "context" |
| "errors" |
| "fmt" |
| "net/http" |
| "os" |
| "strings" |
| |
| "github.com/golang/protobuf/ptypes/any" |
| "github.com/maruel/subcommands" |
| "go.chromium.org/luci/auth" |
| "go.chromium.org/luci/luciexe/build" |
| ftxproto "go.fuchsia.dev/infra/cmd/ftxtest/proto" |
| ) |
| |
| func cmdRun(authOpts auth.Options) *subcommands.Command { |
| return &subcommands.Command{ |
| UsageLine: "run", |
| ShortDesc: "runs test", |
| LongDesc: "Runs test based on luciexe protocol.", |
| CommandRun: func() subcommands.CommandRun { |
| r := &runImpl{} |
| r.Init(authOpts) |
| return r |
| }, |
| } |
| } |
| |
| type runImpl struct { |
| commonFlags |
| |
| subcommands.CommandRunBase |
| } |
| |
| func (r *runImpl) Init(defaultAuthOpts auth.Options) { |
| r.commonFlags.Init(defaultAuthOpts) |
| } |
| |
| func (r *runImpl) Run(a subcommands.Application, args []string, env subcommands.Env) int { |
| if err := r.commonFlags.Parse(); err != nil { |
| fmt.Fprintf(os.Stderr, "Error parsing common flags: %v\n", err) |
| return 1 |
| } |
| r.luciexeInit() |
| // luciexe uses os.exit to exit. |
| return 0 |
| } |
| |
| func (r *runImpl) luciexeInit() { |
| buildInput := &ftxproto.InputProperties{} |
| var writeOutputProps func(*any.Any) |
| build.Main(buildInput, &writeOutputProps, nil, func(ctx context.Context, extraArgs []string, state *build.State) error { |
| if len(buildInput.Name) == 0 { |
| return errors.New("Name is required.") |
| } |
| authenticator := auth.NewAuthenticator(ctx, auth.SilentLogin, r.parsedAuthOpts) |
| httpClient, err := authenticator.Client() |
| if err != nil { |
| fmt.Fprintf(os.Stderr, "You need to login first by running:\n") |
| fmt.Fprintf(os.Stderr, " luci-auth login -scopes %q\n", strings.Join(r.parsedAuthOpts.Scopes, " ")) |
| return errors.New("Not logged in.") |
| } |
| _, _, err = LaunchTaskStep(ctx, httpClient, buildInput) |
| if err != nil { |
| return fmt.Errorf("LaunchTaskStep: %v", err) |
| } |
| return nil |
| }) |
| } |
| |
| func LaunchTaskStep(ctx context.Context, httpClient *http.Client, buildInput *ftxproto.InputProperties) (*Swarming, string, error) { |
| step, ctx := build.StartStep(ctx, "Launch Swarming Task") |
| instance := instance(buildInput) |
| swarming, err := NewSwarming(ctx, httpClient, instance) |
| if err != nil { |
| step.End(err) |
| return nil, "", fmt.Errorf("NewSwarming: %v", err) |
| } |
| task, err := swarming.LaunchTask(buildInput) |
| if err != nil { |
| step.End(err) |
| return nil, "", fmt.Errorf("LaunchTask: %v", err) |
| } |
| md := fmt.Sprintf("* [swarming task](https://%s.appspot.com/task?id=%s)", instance, task.TaskId) |
| step.SetSummaryMarkdown(md) |
| step.End(nil) |
| return swarming, task.TaskId, nil |
| } |
| |
| func instance(buildInput *ftxproto.InputProperties) string { |
| if buildInput.External { |
| return "chromium-swarm" |
| } else { |
| return "chrome-swarming" |
| } |
| } |