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