| // Copyright 2021 The Fuchsia Authors. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "context" |
| "encoding/json" |
| "errors" |
| "fmt" |
| "os" |
| |
| "github.com/maruel/subcommands" |
| "go.chromium.org/luci/auth" |
| buildbucketpb "go.chromium.org/luci/buildbucket/proto" |
| "go.chromium.org/luci/luciexe/exe" |
| ) |
| |
| func cmdManifest(authOpts auth.Options) *subcommands.Command { |
| return &subcommands.Command{ |
| UsageLine: "manifest -gitiles-remote <gitiles-remote> -base-commit <sha1> -builder <project/bucket/builder> -json-output <json-output>", |
| ShortDesc: "Extract assembly_manifest_url output property from CI.", |
| LongDesc: "Extract assembly_manifest_url output property from CI.", |
| CommandRun: func() subcommands.CommandRun { |
| c := &manifestRun{} |
| c.Init(authOpts) |
| return c |
| }, |
| } |
| } |
| |
| type manifestRun struct { |
| commonFlags |
| } |
| |
| func (c *manifestRun) Init(defaultAuthOpts auth.Options) { |
| c.commonFlags.Init(defaultAuthOpts) |
| } |
| |
| func (c *manifestRun) Parse() error { |
| if err := c.commonFlags.Parse(); err != nil { |
| return err |
| } |
| return nil |
| } |
| |
| func (c *manifestRun) main() error { |
| ctx := context.Background() |
| |
| fieldMaskPaths1 := []string{ |
| "builds.*.id", |
| "builds.*.status", |
| "builds.*.output.properties.fields.assembly_manifest_url", |
| } |
| fieldMaskPaths2 := []string{ |
| "id", |
| "status", |
| "output.properties.fields.assembly_manifest_url", |
| } |
| build, err := getBuild(ctx, c.commonFlags, fieldMaskPaths1, fieldMaskPaths2) |
| if err != nil { |
| return err |
| } |
| buildLink := fmt.Sprintf("https://%s/build/%d", c.bbHost, build.Id) |
| if build.Status != buildbucketpb.Status_SUCCESS { |
| return buildNotSuccessfulError{ |
| msg: fmt.Sprintf("a successful build is needed to retrieve an output property from the build, but got status %s, see %s", build.Status, buildLink), |
| status: build.Status, |
| } |
| } |
| |
| var assembly_manifest_url string |
| exe.ParseProperties(build.Output.Properties, map[string]any{ |
| "assembly_manifest_url": &assembly_manifest_url, |
| }) |
| |
| out := os.Stdout |
| if c.jsonOutput != "-" { |
| out, err = os.Create(c.jsonOutput) |
| if err != nil { |
| return err |
| } |
| defer out.Close() |
| } |
| data, err := json.MarshalIndent(assembly_manifest_url, "", " ") |
| if err != nil { |
| return fmt.Errorf("failed to marshal JSON: %w", err) |
| } |
| _, err = out.Write(data) |
| return err |
| } |
| |
| func (c *manifestRun) Run(a subcommands.Application, args []string, env subcommands.Env) int { |
| if err := c.Parse(); err != nil { |
| fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err) |
| return 1 |
| } |
| |
| if err := c.main(); err != nil { |
| fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err) |
| var maybeBuildNotSuccessfulError buildNotSuccessfulError |
| if errors.As(err, &maybeBuildNotSuccessfulError) { |
| return buildNotSuccessfulExitCode |
| } |
| return 1 |
| } |
| return 0 |
| } |