forked from gobuffalo/buffalo
/
dev.go
129 lines (115 loc) · 2.99 KB
/
dev.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package cmd
import (
"bytes"
"context"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"github.com/fatih/color"
"github.com/gobuffalo/buffalo/generators/assets/webpack"
rg "github.com/gobuffalo/buffalo/generators/refresh"
"github.com/gobuffalo/buffalo/meta"
"github.com/markbates/refresh/refresh"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
)
var devOptions = struct {
Debug bool
}{}
// devCmd represents the dev command
var devCmd = &cobra.Command{
Use: "dev",
Short: "Runs your Buffalo app in 'development' mode",
Long: `Runs your Buffalo app in 'development' mode.
This includes rebuilding your application when files change.
This behavior can be changed in your .buffalo.dev.yml file.`,
RunE: func(c *cobra.Command, args []string) error {
if runtime.GOOS == "windows" {
color.NoColor = true
}
defer func() {
msg := "There was a problem starting the dev server, Please review the troubleshooting docs: %s\n"
cause := "Unknown"
if r := recover(); r != nil {
if err, ok := r.(error); ok {
cause = err.Error()
}
}
logrus.Errorf(msg, cause)
}()
os.Setenv("GO_ENV", "development")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
wg, ctx := errgroup.WithContext(ctx)
wg.Go(func() error {
return startDevServer(ctx)
})
wg.Go(func() error {
return startWebpack(ctx)
})
err := wg.Wait()
if err != context.Canceled {
return errors.WithStack(err)
}
return nil
},
}
func startWebpack(ctx context.Context) error {
app := meta.New(".")
if !app.WithWebpack {
// there's no webpack, so don't do anything
return nil
}
if _, err := os.Stat(filepath.Join(app.Root, "node_modules")); err != nil {
tool := "yarn"
if !app.WithYarn {
tool = "npm"
}
if _, err := exec.LookPath(tool); err != nil {
return errors.Errorf("no node_modules directory found, and couldn't find %s to install it with", tool)
}
cmd := exec.CommandContext(ctx, tool, "install")
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return errors.WithStack(err)
}
}
cmd := exec.CommandContext(ctx, webpack.BinPath, "--watch")
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
return cmd.Run()
}
func startDevServer(ctx context.Context) error {
cfgFile := "./.buffalo.dev.yml"
_, err := os.Stat(cfgFile)
if err != nil {
err = rg.Run("./", map[string]interface{}{
"name": "buffalo",
})
}
c := &refresh.Configuration{}
err = c.Load(cfgFile)
if err != nil {
return err
}
c.Debug = devOptions.Debug
if b, err := ioutil.ReadFile("database.yml"); err == nil {
if bytes.Contains(b, []byte("sqlite")) {
c.BuildFlags = append(c.BuildFlags, "-tags", "sqlite")
}
}
r := refresh.NewWithContext(c, ctx)
return r.Start()
}
func init() {
devCmd.Flags().BoolVarP(&devOptions.Debug, "debug", "d", false, "use delve to debug the app")
decorate("dev", devCmd)
RootCmd.AddCommand(devCmd)
}