github.com/mayra-cabrera/buffalo@v0.9.4-0.20170814145312-66d2e7772f11/buffalo/cmd/setup.go (about)

     1  package cmd
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"os"
     8  	"os/exec"
     9  	"strings"
    10  
    11  	"golang.org/x/sync/errgroup"
    12  
    13  	"github.com/gobuffalo/envy"
    14  	"github.com/markbates/deplist"
    15  	"github.com/pkg/errors"
    16  	"github.com/spf13/cobra"
    17  )
    18  
    19  var setupOptions = struct {
    20  	verbose       bool
    21  	updateGoDeps  bool
    22  	dropDatabases bool
    23  }{}
    24  
    25  type setupCheck func() error
    26  
    27  var setupCmd = &cobra.Command{
    28  	Use:   "setup",
    29  	Short: "Setups a newly created, or recently checked out application.",
    30  	Long: `Setup runs through checklist to make sure dependencies are setup correcly.
    31  
    32  Dependencies (if used):
    33  * Runs "dep ensure" to install required Go dependencies.
    34  
    35  Asset Pipeline (if used):
    36  * Runs "npm install" or "yarn install" to install asset dependencies.
    37  
    38  Database (if used):
    39  * Runs "buffalo db create -a" to create databases.
    40  * Runs "buffalo db migrate" to run database migrations.
    41  * Runs "buffalo task db:seed" to seed the database (if the task exists).
    42  
    43  Tests:
    44  * Runs "buffalo test" to confirm the application's tests are running properly.
    45  `,
    46  	RunE: func(cmd *cobra.Command, args []string) error {
    47  		for _, check := range []setupCheck{assetCheck, updateGoDepsCheck, databaseCheck, testCheck} {
    48  			err := check()
    49  			if err != nil {
    50  				return errors.WithStack(err)
    51  			}
    52  		}
    53  		return nil
    54  	},
    55  }
    56  
    57  func updateGoDepsCheck() error {
    58  	deps, _ := deplist.List()
    59  	if _, err := os.Stat("Gopkg.toml"); err == nil {
    60  		// use github.com/golang/dep
    61  		args := []string{"ensure"}
    62  		if setupOptions.verbose {
    63  			args = append(args, "-v")
    64  		}
    65  		if setupOptions.updateGoDeps {
    66  			args = append(args, "--update")
    67  		}
    68  		err := run(exec.Command("dep", args...))
    69  		if err != nil {
    70  			return errors.WithStack(err)
    71  		}
    72  		return nil
    73  	}
    74  
    75  	// go old school with the installation
    76  	ctx, cancel := context.WithCancel(context.Background())
    77  	defer cancel()
    78  	wg, ctx := errgroup.WithContext(ctx)
    79  	deps, err := deplist.List()
    80  	if err != nil {
    81  		return errors.WithStack(err)
    82  	}
    83  	for dep := range deps {
    84  		args := []string{"get"}
    85  		if setupOptions.verbose {
    86  			args = append(args, "-v")
    87  		}
    88  		if setupOptions.updateGoDeps {
    89  			args = append(args, "-u")
    90  		}
    91  		args = append(args, dep)
    92  		c := exec.Command(envy.Get("GO_BIN", "go"), args...)
    93  		f := func() error {
    94  			return run(c)
    95  		}
    96  		wg.Go(f)
    97  	}
    98  	err = wg.Wait()
    99  	if err != nil {
   100  		return errors.Errorf("We encountered the following error trying to install and update the dependencies for this application:\n%s", err)
   101  	}
   102  	return nil
   103  }
   104  
   105  func testCheck() error {
   106  	err := run(exec.Command("buffalo", "test"))
   107  	if err != nil {
   108  		return errors.Errorf("We encountered the following error when trying to run your applications tests:\n%s", err)
   109  	}
   110  	return nil
   111  }
   112  
   113  func databaseCheck() error {
   114  	if _, err := os.Stat("./database.yml"); err != nil {
   115  		// no database.yml, so move on
   116  		return nil
   117  	}
   118  	for _, check := range []setupCheck{dbCreateCheck, dbMigrateCheck, dbSeedCheck} {
   119  		err := check()
   120  		if err != nil {
   121  			return err
   122  		}
   123  	}
   124  	return nil
   125  }
   126  
   127  func dbCreateCheck() error {
   128  	if setupOptions.dropDatabases {
   129  		err := run(exec.Command("buffalo", "db", "drop", "-a"))
   130  		if err != nil {
   131  			return errors.Errorf("We encountered an error when trying to drop your application's databases. Please check to make sure that your database server is running and that the username and passwords found in the database.yml are properly configured and set up on your database server.\n %s", err)
   132  		}
   133  	}
   134  	err := run(exec.Command("buffalo", "db", "create", "-a"))
   135  	if err != nil {
   136  		return errors.Errorf("We encountered an error when trying to create your application's databases. Please check to make sure that your database server is running and that the username and passwords found in the database.yml are properly configured and set up on your database server.\n %s", err)
   137  	}
   138  	return nil
   139  }
   140  
   141  func dbMigrateCheck() error {
   142  	err := run(exec.Command("buffalo", "db", "migrate"))
   143  	if err != nil {
   144  		return errors.Errorf("We encountered the following error when trying to migrate your database:\n%s", err)
   145  	}
   146  	return nil
   147  }
   148  
   149  func dbSeedCheck() error {
   150  	cmd := exec.Command("buffalo", "t", "list")
   151  	out, err := cmd.Output()
   152  	if err != nil {
   153  		// no tasks configured, so return
   154  		return nil
   155  	}
   156  	if bytes.Contains(out, []byte("db:seed")) {
   157  		err := run(exec.Command("buffalo", "task", "db:seed"))
   158  		if err != nil {
   159  			return errors.Errorf("We encountered the following error when trying to seed your database:\n%s", err)
   160  		}
   161  	}
   162  	return nil
   163  }
   164  
   165  func assetCheck() error {
   166  	if _, err := os.Stat("./yarn.lock"); err == nil {
   167  		return yarnCheck()
   168  	}
   169  	if _, err := os.Stat("./package.json"); err == nil {
   170  		return npmCheck()
   171  	}
   172  	// no asset pipeline, so move on.
   173  	return nil
   174  }
   175  
   176  func npmCheck() error {
   177  	err := nodeCheck()
   178  	if err != nil {
   179  		return errors.WithStack(err)
   180  	}
   181  	err = run(exec.Command("npm", "install", "--no-progress"))
   182  	if err != nil {
   183  		return errors.Errorf("We encountered the following error when trying to install your asset dependencies using npm:\n%s", err)
   184  	}
   185  	return nil
   186  }
   187  
   188  func yarnCheck() error {
   189  	err := nodeCheck()
   190  	if err != nil {
   191  		return errors.WithStack(err)
   192  	}
   193  	if _, err := exec.LookPath("yarn"); err != nil {
   194  		err := run(exec.Command("npm", "install", "yarn"))
   195  		if err != nil {
   196  			return errors.Errorf("This application require yarn, and we could not find it installed on your system. We tried to install it for you, but ran into the following error:\n%s", err)
   197  		}
   198  	}
   199  	err = run(exec.Command("yarn", "--no-progress", "install"))
   200  	if err != nil {
   201  		return errors.Errorf("We encountered the following error when trying to install your asset dependencies using yarn:\n%s", err)
   202  	}
   203  	return nil
   204  }
   205  
   206  func nodeCheck() error {
   207  	if _, err := exec.LookPath("node"); err != nil {
   208  		return errors.New("this application requires node, and we could not find it installed on your system please install node and try again")
   209  	}
   210  	if _, err := exec.LookPath("npm"); err != nil {
   211  		return errors.New("this application requires npm, and we could not find it installed on your system please install npm and try again")
   212  	}
   213  	return nil
   214  }
   215  
   216  func run(cmd *exec.Cmd) error {
   217  	fmt.Printf("--> %s\n", strings.Join(cmd.Args, " "))
   218  	cmd.Stdin = os.Stdin
   219  	cmd.Stderr = os.Stderr
   220  	cmd.Stdout = os.Stdout
   221  	return cmd.Run()
   222  }
   223  
   224  func init() {
   225  	setupCmd.Flags().BoolVarP(&setupOptions.verbose, "verbose", "v", false, "run with verbose output")
   226  	setupCmd.Flags().BoolVarP(&setupOptions.updateGoDeps, "update", "u", false, "run go get -u against the application's Go dependencies")
   227  	setupCmd.Flags().BoolVarP(&setupOptions.dropDatabases, "drop", "d", false, "drop existing databases")
   228  
   229  	decorate("setup", setupCmd)
   230  	RootCmd.AddCommand(setupCmd)
   231  }