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

     1  // Copyright 2022 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  	"encoding/json"
     9  	"errors"
    10  	"fmt"
    11  	"os"
    12  
    13  	"github.com/maruel/subcommands"
    14  
    15  	"go.fuchsia.dev/infra/cmd/size_check/sizes"
    16  )
    17  
    18  func cmdBudgets() *subcommands.Command {
    19  	return &subcommands.Command{
    20  		UsageLine: "budgets -binary-sizes-json-input <binary-sizes-json-input>",
    21  		ShortDesc: "Check if input binary sizes object exceeds one or more budgets.",
    22  		LongDesc:  "Check if input binary sizes object exceeds one or more budgets.",
    23  		CommandRun: func() subcommands.CommandRun {
    24  			c := &budgetsRun{}
    25  			c.Init()
    26  			return c
    27  		},
    28  	}
    29  }
    30  
    31  type budgetsRun struct {
    32  	subcommands.CommandRunBase
    33  	binarySizesJSONInput string
    34  }
    35  
    36  func (c *budgetsRun) Init() {
    37  	c.Flags.StringVar(&c.binarySizesJSONInput, "binary-sizes-json-input", "", "Path for input binary sizes object as JSON.")
    38  }
    39  
    40  func (c *budgetsRun) Parse() error {
    41  	if c.binarySizesJSONInput == "" {
    42  		return errors.New("-binary-sizes-json-input is required")
    43  	}
    44  	return nil
    45  }
    46  
    47  func (c *budgetsRun) main() error {
    48  	jsonInput, err := os.ReadFile(c.binarySizesJSONInput)
    49  	if err != nil {
    50  		return err
    51  	}
    52  	var rawBinarySizes map[string]any
    53  	if err := json.Unmarshal(jsonInput, &rawBinarySizes); err != nil {
    54  		return err
    55  	}
    56  	binarySizes, err := sizes.Parse(rawBinarySizes)
    57  	if err != nil {
    58  		return err
    59  	}
    60  	for component, metadata := range binarySizes {
    61  		if metadata.Size > metadata.Budget {
    62  			return fmt.Errorf("%q size exceeds budget by %d bytes", component, metadata.Size-metadata.Budget)
    63  		}
    64  	}
    65  	return nil
    66  }
    67  
    68  func (c *budgetsRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
    69  	if err := c.Parse(); err != nil {
    70  		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
    71  		return 1
    72  	}
    73  	if err := c.main(); err != nil {
    74  		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
    75  		return 1
    76  	}
    77  	return 0
    78  }