github.com/segakazzz/buffalo@v0.16.22-0.20210119082501-1f52048d3feb/buffalo/cmd/build.go (about)

     1  package cmd
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"log"
     7  	"os"
     8  	"os/exec"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/gobuffalo/buffalo/genny/build"
    13  	"github.com/gobuffalo/genny/v2"
    14  	"github.com/gobuffalo/logger"
    15  	"github.com/gobuffalo/meta"
    16  	"github.com/markbates/sigtx"
    17  	"github.com/spf13/cobra"
    18  )
    19  
    20  var buildOptions = struct {
    21  	*build.Options
    22  	SkipAssets             bool
    23  	SkipBuildDeps          bool
    24  	Debug                  bool
    25  	Tags                   string
    26  	SkipTemplateValidation bool
    27  	DryRun                 bool
    28  	Verbose                bool
    29  	bin                    string
    30  }{
    31  	Options: &build.Options{
    32  		BuildTime: time.Now(),
    33  	},
    34  }
    35  
    36  var xbuildCmd = &cobra.Command{
    37  	Use:     "build",
    38  	Aliases: []string{"b", "bill", "install"},
    39  	Short:   "Build the application binary, including bundling of assets (packr & webpack)",
    40  	RunE: func(cmd *cobra.Command, args []string) error {
    41  		ctx, cancel := sigtx.WithCancel(context.Background(), os.Interrupt)
    42  		defer cancel()
    43  
    44  		pwd, err := os.Getwd()
    45  		if err != nil {
    46  			return err
    47  		}
    48  
    49  		buildOptions.App = meta.New(pwd)
    50  		if len(buildOptions.bin) > 0 {
    51  			buildOptions.App.Bin = buildOptions.bin
    52  		}
    53  
    54  		buildOptions.Options.WithAssets = !buildOptions.SkipAssets
    55  		buildOptions.Options.WithBuildDeps = !buildOptions.SkipBuildDeps
    56  
    57  		run := genny.WetRunner(ctx)
    58  		if buildOptions.DryRun {
    59  			run = genny.DryRunner(ctx)
    60  		}
    61  
    62  		if buildOptions.Verbose || buildOptions.Debug {
    63  			lg := logger.New(logger.DebugLevel)
    64  			run.Logger = lg
    65  			// plog.Logger = lg
    66  			buildOptions.BuildFlags = append(buildOptions.BuildFlags, "-v")
    67  		}
    68  
    69  		opts := buildOptions.Options
    70  		opts.BuildVersion = buildVersion(opts.BuildTime.Format(time.RFC3339))
    71  
    72  		if buildOptions.Tags != "" {
    73  			opts.Tags = append(opts.Tags, buildOptions.Tags)
    74  		}
    75  
    76  		if !buildOptions.SkipTemplateValidation {
    77  			opts.TemplateValidators = append(opts.TemplateValidators, build.PlushValidator, build.GoTemplateValidator)
    78  		}
    79  
    80  		if cmd.CalledAs() == "install" {
    81  			opts.GoCommand = "install"
    82  		}
    83  		clean := build.Cleanup(opts)
    84  		// defer clean(run)
    85  		defer func() {
    86  			if err := clean(run); err != nil {
    87  				log.Fatal("build:clean", err)
    88  			}
    89  		}()
    90  		if err := run.WithNew(build.New(opts)); err != nil {
    91  			return err
    92  		}
    93  		return run.Run()
    94  	},
    95  }
    96  
    97  func init() {
    98  	RootCmd.AddCommand(xbuildCmd)
    99  
   100  	xbuildCmd.Flags().StringVarP(&buildOptions.bin, "output", "o", buildOptions.Bin, "set the name of the binary")
   101  	xbuildCmd.Flags().StringVarP(&buildOptions.Tags, "tags", "t", "", "compile with specific build tags")
   102  	xbuildCmd.Flags().BoolVarP(&buildOptions.ExtractAssets, "extract-assets", "e", false, "extract the assets and put them in a distinct archive")
   103  	xbuildCmd.Flags().BoolVarP(&buildOptions.SkipAssets, "skip-assets", "k", false, "skip running webpack and building assets")
   104  	xbuildCmd.Flags().BoolVarP(&buildOptions.SkipBuildDeps, "skip-build-deps", "", false, "skip building dependencies")
   105  	xbuildCmd.Flags().BoolVarP(&buildOptions.Static, "static", "s", false, "build a static binary using  --ldflags '-linkmode external -extldflags \"-static\"'")
   106  	xbuildCmd.Flags().StringVar(&buildOptions.LDFlags, "ldflags", "", "set any ldflags to be passed to the go build")
   107  	xbuildCmd.Flags().BoolVarP(&buildOptions.Verbose, "verbose", "v", false, "print debugging information")
   108  	xbuildCmd.Flags().BoolVar(&buildOptions.DryRun, "dry-run", false, "runs the build 'dry'")
   109  	xbuildCmd.Flags().BoolVar(&buildOptions.SkipTemplateValidation, "skip-template-validation", false, "skip validating templates")
   110  	xbuildCmd.Flags().BoolVar(&buildOptions.CleanAssets, "clean-assets", false, "will delete public/assets before calling webpack")
   111  	xbuildCmd.Flags().StringVarP(&buildOptions.Environment, "environment", "", "development", "set the environment for the binary")
   112  	xbuildCmd.Flags().StringVar(&buildOptions.Mod, "mod", "", "-mod flag for go build")
   113  }
   114  
   115  func buildVersion(version string) string {
   116  	vcs := buildOptions.VCS
   117  
   118  	if len(vcs) == 0 {
   119  		return version
   120  	}
   121  
   122  	ctx := context.Background()
   123  	run := genny.WetRunner(ctx)
   124  	if buildOptions.DryRun {
   125  		run = genny.DryRunner(ctx)
   126  	}
   127  
   128  	_, err := exec.LookPath(vcs)
   129  	if err != nil {
   130  		run.Logger.Warnf("could not find %s; defaulting to version %s", vcs, version)
   131  		return vcs
   132  	}
   133  
   134  	var cmd *exec.Cmd
   135  	switch vcs {
   136  	case "git":
   137  		// If .git folder does not exist return default version
   138  		if stat, err := os.Stat(".git"); err != nil || !stat.IsDir() {
   139  			run.Logger.Warnf("could not find .git folder; defaulting to version %s", version)
   140  			return version
   141  		}
   142  
   143  		cmd = exec.Command("git", "rev-parse", "--short", "HEAD")
   144  	case "bzr":
   145  		cmd = exec.Command("bzr", "revno")
   146  	default:
   147  		run.Logger.Warnf("could not find %s; defaulting to version %s", vcs, version)
   148  		return vcs
   149  	}
   150  
   151  	out := &bytes.Buffer{}
   152  	cmd.Stdout = out
   153  	run.WithRun(func(r *genny.Runner) error {
   154  		return r.Exec(cmd)
   155  	})
   156  
   157  	if err := run.Run(); err != nil {
   158  		run.Logger.Error(err)
   159  		return version
   160  	}
   161  
   162  	if out.String() != "" {
   163  		return strings.TrimSpace(out.String())
   164  	}
   165  
   166  	return version
   167  }