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  }