blob: 58432b0465b0d12d7c6e2765d210a07186e5bac9 [file] [log] [blame]
// Copyright 2020 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"
"github.com/maruel/subcommands"
"go.chromium.org/luci/auth"
buildbucketpb "go.chromium.org/luci/buildbucket/proto"
"google.golang.org/genproto/protobuf/field_mask"
)
func cmdRevision(authOpts auth.Options) *subcommands.Command {
return &subcommands.Command{
UsageLine: "revision -builder project1/bucket1/builder1, ... [common options]",
ShortDesc: "Get the last known good revision across a set of builders.",
LongDesc: "Get the last known good revision across a set of builders.",
CommandRun: func() subcommands.CommandRun {
c := &revisionRun{}
c.Init(authOpts)
return c
},
}
}
type revisionRun struct {
commonFlags
builders builders
}
func (c *revisionRun) Init(defaultAuthOpts auth.Options) {
c.commonFlags.Init(defaultAuthOpts)
c.Flags.Var(&c.builders, "builder", "Builder ID as project/bucket/builder. Repeatable")
}
func (c *revisionRun) checkFlags() error {
if err := c.commonFlags.checkFlags(); err != nil {
return err
}
if len(c.builders) == 0 {
return errors.New("at least one -builder is required")
}
return nil
}
func (c *revisionRun) main(a subcommands.Application) error {
ctx := context.Background()
client, err := newBuildbucketClient(ctx, c.parsedAuthOpts, c.buildbucketHost)
if err != nil {
return fmt.Errorf("failed to initialize client: %w", err)
}
// Do not retrieve any fields additional to default input, as we only need revision.
mask := &field_mask.FieldMask{
Paths: []string{},
}
builds, err := client.GetBuilds(ctx, c.builders, mask, c.searchRange)
if err != nil {
return fmt.Errorf("failed to query builds: %w", err)
}
// Pass an accessorFunc which returns a build's revision.
revision, err := getLastKnownGood(builds, c.gitilesRef, func(build *buildbucketpb.Build) any {
// Skip manually triggered builds, which do not have a gitiles commit.
if build.Input.GitilesCommit == nil {
return nil
}
return build.Input.GitilesCommit.Id
})
if err != nil {
return fmt.Errorf("failed to get last known good revision: %w", err)
}
fmt.Println(revision)
return nil
}
func (c *revisionRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
if err := c.checkFlags(); err != nil {
fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
return 1
}
if err := c.main(a); err != nil {
fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
return 1
}
return 0
}