github.com/orangenpresse/up@v0.6.0/internal/cli/deploy/deploy.go (about)

     1  package deploy
     2  
     3  import (
     4  	"os"
     5  	"time"
     6  
     7  	"github.com/pkg/errors"
     8  	"github.com/tj/go/git"
     9  	"github.com/tj/go/term"
    10  	"github.com/tj/kingpin"
    11  
    12  	"github.com/apex/up"
    13  	"github.com/apex/up/internal/cli/root"
    14  	"github.com/apex/up/internal/setup"
    15  	"github.com/apex/up/internal/stats"
    16  	"github.com/apex/up/internal/util"
    17  	"github.com/apex/up/internal/validate"
    18  )
    19  
    20  func init() {
    21  	cmd := root.Command("deploy", "Deploy the project.").Default()
    22  	stage := cmd.Arg("stage", "Target stage name.").Default("staging").String()
    23  	cmd.Example(`up deploy`, "Deploy the project the staging environment.")
    24  	cmd.Example(`up deploy production`, "Deploy the project to the production environment.")
    25  
    26  	cmd.Action(func(_ *kingpin.ParseContext) error {
    27  		return deploy(*stage)
    28  	})
    29  }
    30  
    31  func deploy(stage string) error {
    32  retry:
    33  	c, p, err := root.Init()
    34  
    35  	// missing up.json non-interactive
    36  	if isMissingConfig(err) && !term.IsTerminal(os.Stdin.Fd()) {
    37  		return errors.New("Cannot find ./up.json configuration file.")
    38  	}
    39  
    40  	// missing up.json interactive
    41  	if isMissingConfig(err) {
    42  		err := setup.Create()
    43  
    44  		if err == setup.ErrNoCredentials {
    45  			return errors.New("Cannot find credentials, visit https://up.docs.apex.sh/#aws_credentials for help.")
    46  		}
    47  
    48  		if err != nil {
    49  			return errors.Wrap(err, "setup")
    50  		}
    51  
    52  		util.Log("Deploying the project and creating resources.")
    53  		goto retry
    54  	}
    55  
    56  	// unrelated error
    57  	if err != nil {
    58  		return errors.Wrap(err, "initializing")
    59  	}
    60  
    61  	// validate stage name
    62  	if err := validate.List(stage, c.Stages.RemoteNames()); err != nil {
    63  		return err
    64  	}
    65  
    66  	// stage overrides
    67  	if err := c.Override(stage); err != nil {
    68  		return errors.Wrap(err, "overriding")
    69  	}
    70  
    71  	// git information
    72  	commit, err := getCommit()
    73  	if err != nil {
    74  		return errors.Wrap(err, "fetching git commit")
    75  	}
    76  
    77  	defer util.Pad()()
    78  	start := time.Now()
    79  
    80  	if err := p.Init(stage); err != nil {
    81  		return errors.Wrap(err, "initializing")
    82  	}
    83  
    84  	if err := p.Deploy(up.Deploy{
    85  		Stage:  stage,
    86  		Commit: commit.Describe(),
    87  		Author: commit.Author.Name,
    88  	}); err != nil {
    89  		return err
    90  	}
    91  
    92  	stats.Track("Deploy", map[string]interface{}{
    93  		"duration":             util.MillisecondsSince(start),
    94  		"type":                 c.Type,
    95  		"regions":              c.Regions,
    96  		"stage":                stage,
    97  		"proxy_timeout":        c.Proxy.Timeout,
    98  		"header_rules_count":   len(c.Headers),
    99  		"redirect_rules_count": len(c.Redirects),
   100  		"inject_rules_count":   len(c.Inject),
   101  		"environment_count":    len(c.Environment),
   102  		"dns_zone_count":       len(c.DNS.Zones),
   103  		"stage_count":          len(c.Stages.List()),
   104  		"stage_domain_count":   len(c.Stages.Domains()),
   105  		"lambda_memory":        c.Lambda.Memory,
   106  		"has_cors":             c.CORS != nil,
   107  		"has_logs":             !c.Logs.Disable,
   108  		"has_profile":          c.Profile != "",
   109  		"has_error_pages":      !c.ErrorPages.Disable,
   110  		"app_name_hash":        util.Md5(c.Name),
   111  		"is_git":               commit.Author.Name != "",
   112  	})
   113  
   114  	stats.Flush()
   115  	return nil
   116  }
   117  
   118  // isMissingConfig returns true if the error represents a missing up.json.
   119  func isMissingConfig(err error) bool {
   120  	err = errors.Cause(err)
   121  	e, ok := err.(*os.PathError)
   122  	return ok && e.Path == "up.json"
   123  }
   124  
   125  // getCommit returns the git information when available.
   126  func getCommit() (git.Commit, error) {
   127  	c, err := git.GetCommit(".", "HEAD")
   128  	if err != nil && !isIgnorable(err) {
   129  		return git.Commit{}, err
   130  	}
   131  
   132  	if c == nil {
   133  		return git.Commit{}, nil
   134  	}
   135  
   136  	return *c, nil
   137  }
   138  
   139  // isIgnorable returns true if the GIT error is ignorable.
   140  func isIgnorable(err error) bool {
   141  	switch err {
   142  	case git.ErrLookup, git.ErrNoRepo, git.ErrDirty:
   143  		return true
   144  	default:
   145  		return false
   146  	}
   147  }