go.fuchsia.dev/infra@v0.0.0-20240507153436-9b593402251b/cmd/size_diff/manifest.go (about)

     1  // Copyright 2021 The Fuchsia Authors.
     2  // Use of this source code is governed by a BSD-style license that can be
     3  // found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"context"
     9  	"encoding/json"
    10  	"errors"
    11  	"fmt"
    12  	"os"
    13  
    14  	"github.com/maruel/subcommands"
    15  	"go.chromium.org/luci/auth"
    16  	buildbucketpb "go.chromium.org/luci/buildbucket/proto"
    17  	"go.chromium.org/luci/luciexe/exe"
    18  )
    19  
    20  const assemblyManifestURLOutputProp = "assembly_manifest_url"
    21  
    22  func cmdManifest(authOpts auth.Options) *subcommands.Command {
    23  	return &subcommands.Command{
    24  		UsageLine: "manifest -gitiles-remote <gitiles-remote> -base-commit <sha1> -builder <project/bucket/builder>  -json-output <json-output>",
    25  		ShortDesc: "Extract assembly_manifest_url output property from CI.",
    26  		LongDesc:  "Extract assembly_manifest_url output property from CI.",
    27  		CommandRun: func() subcommands.CommandRun {
    28  			c := &manifestRun{}
    29  			c.Init(authOpts)
    30  			return c
    31  		},
    32  	}
    33  }
    34  
    35  type manifestRun struct {
    36  	commonFlags
    37  }
    38  
    39  func (c *manifestRun) Init(defaultAuthOpts auth.Options) {
    40  	c.commonFlags.Init(defaultAuthOpts)
    41  }
    42  
    43  func (c *manifestRun) Parse() error {
    44  	if err := c.commonFlags.Parse(); err != nil {
    45  		return err
    46  	}
    47  	return nil
    48  }
    49  
    50  func (c *manifestRun) main() error {
    51  	ctx := context.Background()
    52  	build, err := getBuild(ctx, c.commonFlags, []string{assemblyManifestURLOutputProp})
    53  	if err != nil {
    54  		return err
    55  	}
    56  	buildLink := fmt.Sprintf("https://%s/build/%d", c.bbHost, build.Id)
    57  	if build.Status != buildbucketpb.Status_SUCCESS {
    58  		return buildNotSuccessfulError{
    59  			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),
    60  			status: build.Status,
    61  		}
    62  	}
    63  
    64  	var assemblyManifestURL string
    65  	exe.ParseProperties(build.Output.Properties, map[string]any{
    66  		assemblyManifestURLOutputProp: &assemblyManifestURL,
    67  	})
    68  
    69  	out := os.Stdout
    70  	if c.jsonOutput != "-" {
    71  		out, err = os.Create(c.jsonOutput)
    72  		if err != nil {
    73  			return err
    74  		}
    75  		defer out.Close()
    76  	}
    77  	data, err := json.MarshalIndent(assemblyManifestURL, "", "  ")
    78  	if err != nil {
    79  		return fmt.Errorf("failed to marshal JSON: %w", err)
    80  	}
    81  	_, err = out.Write(data)
    82  	return err
    83  }
    84  
    85  func (c *manifestRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
    86  	if err := c.Parse(); err != nil {
    87  		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
    88  		return 1
    89  	}
    90  
    91  	if err := c.main(); err != nil {
    92  		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
    93  		var maybeBuildNotSuccessfulError buildNotSuccessfulError
    94  		if errors.As(err, &maybeBuildNotSuccessfulError) {
    95  			return buildNotSuccessfulExitCode
    96  		}
    97  		return 1
    98  	}
    99  	return 0
   100  }