github.com/motyar/up@v0.2.10/project.go (about) 1 package up 2 3 import ( 4 "io" 5 "os" 6 "os/exec" 7 "time" 8 9 "github.com/apex/log" 10 "github.com/pkg/errors" 11 12 "github.com/apex/up/config" 13 "github.com/apex/up/internal/util" 14 "github.com/apex/up/platform" 15 "github.com/apex/up/platform/event" 16 ) 17 18 // Project manager. 19 type Project struct { 20 config *Config 21 platform platform.Interface 22 events event.Events 23 } 24 25 // New project. 26 func New(c *Config, events event.Events) *Project { 27 return &Project{ 28 config: c, 29 events: events, 30 } 31 } 32 33 // WithPlatform to `platform`. 34 func (p *Project) WithPlatform(platform platform.Interface) *Project { 35 p.platform = platform 36 return p 37 } 38 39 // HookCommand returns a hook command by name or empty hook. 40 func (p *Project) HookCommand(name string) config.Hook { 41 switch name { 42 case "build": 43 return p.config.Hooks.Build 44 case "clean": 45 return p.config.Hooks.Clean 46 default: 47 return nil 48 } 49 } 50 51 // RunHook runs a hook by name. 52 func (p *Project) RunHook(name string) error { 53 hook := p.HookCommand(name) 54 55 if hook.IsEmpty() { 56 log.Debugf("hook %s is not defined", name) 57 return nil 58 } 59 60 defer p.events.Time("hook", event.Fields{ 61 "name": name, 62 })() 63 64 for _, command := range hook { 65 log.Debugf("hook %q command %q", name, command) 66 67 cmd := exec.Command("sh", "-c", command) 68 cmd.Env = os.Environ() 69 cmd.Env = append(cmd.Env, util.Env(p.config.Environment)...) 70 cmd.Env = append(cmd.Env, "PATH=node_modules/.bin:"+os.Getenv("PATH")) 71 72 b, err := cmd.CombinedOutput() 73 if err != nil { 74 return errors.Errorf("%q: %s", command, b) 75 } 76 } 77 78 return nil 79 } 80 81 // Build the project. 82 func (p *Project) Build() error { 83 defer p.events.Time("platform.build", nil)() 84 85 if err := p.RunHook("build"); err != nil { 86 return errors.Wrap(err, "build hook") 87 } 88 89 return p.platform.Build() 90 } 91 92 // Deploy the project. 93 func (p *Project) Deploy(stage string) error { 94 defer p.events.Time("deploy", nil)() 95 96 if err := p.Build(); err != nil { 97 return errors.Wrap(err, "building") 98 } 99 100 if err := p.deploy(stage); err != nil { 101 return errors.Wrap(err, "deploying") 102 } 103 104 if err := p.RunHook("clean"); err != nil { 105 return errors.Wrap(err, "clean hook") 106 } 107 108 return nil 109 } 110 111 // deploy stage. 112 func (p *Project) deploy(stage string) error { 113 return p.platform.Deploy(stage) 114 } 115 116 // Logs for the project. 117 func (p *Project) Logs(region, query string) platform.Logs { 118 return p.platform.Logs(region, query) 119 } 120 121 // Domains for the project. 122 func (p *Project) Domains() platform.Domains { 123 return p.platform.Domains() 124 } 125 126 // URL returns the endpoint. 127 func (p *Project) URL(region, stage string) (string, error) { 128 return p.platform.URL(region, stage) 129 } 130 131 // Zip returns the zip if supported by the platform. 132 func (p *Project) Zip() (io.Reader, error) { 133 z, ok := p.platform.(platform.Zipper) 134 if !ok { 135 return nil, errors.Errorf("platform does not support zips") 136 } 137 138 return z.Zip(), nil 139 } 140 141 // CreateStack implementation. 142 func (p *Project) CreateStack(region, version string) error { 143 defer p.events.Time("stack.create", event.Fields{ 144 "region": region, 145 "version": version, 146 })() 147 148 return p.platform.CreateStack(region, version) 149 } 150 151 // DeleteStack implementation. 152 func (p *Project) DeleteStack(region string, wait bool) error { 153 defer p.events.Time("stack.delete", event.Fields{ 154 "region": region, 155 })() 156 157 return p.platform.DeleteStack(region, wait) 158 } 159 160 // ShowStack implementation. 161 func (p *Project) ShowStack(region string) error { 162 defer p.events.Time("stack.show", event.Fields{ 163 "region": region, 164 })() 165 166 return p.platform.ShowStack(region) 167 } 168 169 // ShowMetrics implementation. 170 func (p *Project) ShowMetrics(region, stage string, start time.Time) error { 171 defer p.events.Time("metrics", event.Fields{ 172 "region": region, 173 "stage": stage, 174 "start": start, 175 })() 176 177 return p.platform.ShowMetrics(region, stage, start) 178 } 179 180 // PlanStack implementation. 181 func (p *Project) PlanStack(region string) error { 182 defer p.events.Time("stack.plan", event.Fields{ 183 "region": region, 184 })() 185 186 return p.platform.PlanStack(region) 187 } 188 189 // ApplyStack implementation. 190 func (p *Project) ApplyStack(region string) error { 191 defer p.events.Time("stack.apply", event.Fields{ 192 "region": region, 193 })() 194 195 return p.platform.ApplyStack(region) 196 }