github.com/apex/up@v1.7.1/internal/cli/build/build.go (about)

     1  package build
     2  
     3  import (
     4  	"archive/zip"
     5  	"bytes"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"sort"
    10  
    11  	"github.com/dustin/go-humanize"
    12  	"github.com/pkg/errors"
    13  	"github.com/tj/go/term"
    14  	"github.com/tj/kingpin"
    15  
    16  	"github.com/apex/up/internal/cli/root"
    17  	"github.com/apex/up/internal/colors"
    18  	"github.com/apex/up/internal/stats"
    19  	"github.com/apex/up/internal/util"
    20  )
    21  
    22  func init() {
    23  	cmd := root.Command("build", "Build zip file.")
    24  	cmd.Example(`up build`, "Build archive and save to ./out.zip")
    25  	cmd.Example(`up build > /tmp/out.zip`, "Build archive and output to file via stdout.")
    26  	cmd.Example(`up build --size`, "Build archive and list files by size.")
    27  
    28  	stage := cmd.Flag("stage", "Target stage name.").Short('s').Default("staging").String()
    29  	size := cmd.Flag("size", "Show zip contents size information.").Bool()
    30  
    31  	cmd.Action(func(_ *kingpin.ParseContext) error {
    32  		defer util.Pad()()
    33  
    34  		_, p, err := root.Init()
    35  		if err != nil {
    36  			return errors.Wrap(err, "initializing")
    37  		}
    38  
    39  		stats.Track("Build", nil)
    40  
    41  		if err := p.Init(*stage); err != nil {
    42  			return errors.Wrap(err, "initializing")
    43  		}
    44  
    45  		if err := p.Build(true); err != nil {
    46  			return errors.Wrap(err, "building")
    47  		}
    48  
    49  		r, err := p.Zip()
    50  		if err != nil {
    51  			return errors.Wrap(err, "zip")
    52  		}
    53  
    54  		var out io.Writer
    55  		var buf bytes.Buffer
    56  
    57  		switch {
    58  		default:
    59  			out = os.Stdout
    60  		case *size:
    61  			out = &buf
    62  		case term.IsTerminal(os.Stdout.Fd()):
    63  			f, err := os.Create("out.zip")
    64  			if err != nil {
    65  				return errors.Wrap(err, "creating zip")
    66  			}
    67  			defer f.Close()
    68  			out = f
    69  		}
    70  
    71  		if _, err := io.Copy(out, r); err != nil {
    72  			return errors.Wrap(err, "copying")
    73  		}
    74  
    75  		if *size {
    76  			z, err := zip.NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
    77  			if err != nil {
    78  				return errors.Wrap(err, "opening zip")
    79  			}
    80  
    81  			files := z.File
    82  
    83  			sort.Slice(files, func(i int, j int) bool {
    84  				a := files[i]
    85  				b := files[j]
    86  				return a.UncompressedSize64 > b.UncompressedSize64
    87  			})
    88  
    89  			fmt.Printf("\n")
    90  			for _, f := range files {
    91  				size := humanize.Bytes(f.UncompressedSize64)
    92  				fmt.Printf("  %10s %s\n", size, colors.Purple(f.Name))
    93  			}
    94  		}
    95  
    96  		return err
    97  	})
    98  }