github.com/henvic/wedeploycli@v1.7.6-0.20200319005353-3630f582f284/deployment/transport/gogit/gogit.go (about)

     1  package gogit
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"path/filepath"
     8  	"time"
     9  
    10  	"github.com/hashicorp/errwrap"
    11  	"github.com/henvic/wedeploycli/deployment/internal/groupuid"
    12  	"github.com/henvic/wedeploycli/deployment/transport"
    13  	"github.com/henvic/wedeploycli/services"
    14  	"github.com/henvic/wedeploycli/verbose"
    15  	git "gopkg.in/src-d/go-git.v4"
    16  	gitconfig "gopkg.in/src-d/go-git.v4/config"
    17  	"gopkg.in/src-d/go-git.v4/plumbing"
    18  	"gopkg.in/src-d/go-git.v4/plumbing/object"
    19  	gotransport "gopkg.in/src-d/go-git.v4/plumbing/transport"
    20  	"gopkg.in/src-d/go-git.v4/plumbing/transport/http"
    21  )
    22  
    23  // Transport using go-git.
    24  type Transport struct {
    25  	ctx      context.Context
    26  	settings transport.Settings
    27  
    28  	repository *git.Repository
    29  	worktree   *git.Worktree
    30  
    31  	start time.Time
    32  	end   time.Time
    33  }
    34  
    35  // Stage files.
    36  func (t *Transport) Stage(s services.ServiceInfoList) (err error) {
    37  	verbose.Debug("Staging files")
    38  
    39  	for _, s := range s {
    40  		if _, err = t.worktree.Add(filepath.Base(s.Location)); err != nil {
    41  			return err
    42  		}
    43  	}
    44  
    45  	return nil
    46  }
    47  
    48  // Commit adds all files and commits
    49  func (t *Transport) Commit(message string) (commit string, err error) {
    50  	verbose.Debug("Committing changes.")
    51  
    52  	var hash plumbing.Hash
    53  
    54  	hash, err = t.worktree.Commit(message, &git.CommitOptions{
    55  		Author: &object.Signature{
    56  			Name:  "Liferay Cloud user",
    57  			Email: "user@deployment",
    58  			When:  time.Now(),
    59  		},
    60  	})
    61  
    62  	if err != nil {
    63  		return "", errwrap.Wrapf("can't commit: {{err}}", err)
    64  	}
    65  
    66  	commit = hash.String()
    67  
    68  	verbose.Debug("commit", commit)
    69  	return commit, nil
    70  }
    71  
    72  // Push deployment to the Liferay Cloud remote
    73  func (t *Transport) Push() (groupUID string, err error) {
    74  	verbose.Debug("Started uploading deployment package to the infrastructure")
    75  
    76  	t.start = time.Now()
    77  	defer func() {
    78  		t.end = time.Now()
    79  	}()
    80  
    81  	buf := &bytes.Buffer{}
    82  
    83  	o := &git.PushOptions{
    84  		RemoteName: t.getGitRemote(),
    85  		RefSpecs: []gitconfig.RefSpec{
    86  			"+refs/heads/master:refs/heads/master",
    87  		},
    88  		Auth: &http.BasicAuth{
    89  			Username: t.settings.ConfigContext.Token(),
    90  		},
    91  		Progress: buf,
    92  	}
    93  
    94  	err = t.repository.PushContext(t.ctx, o)
    95  
    96  	switch {
    97  	case err == gotransport.ErrAuthenticationRequired:
    98  		return "", errwrap.Wrapf("Invalid credentials", err)
    99  	case err != nil:
   100  		return "", err
   101  	}
   102  
   103  	return groupuid.Extract(buf.String())
   104  }
   105  
   106  // UploadDuration for deployment (only correct after it finishes)
   107  func (t *Transport) UploadDuration() time.Duration {
   108  	return t.end.Sub(t.start)
   109  }
   110  
   111  // Setup as a git repo
   112  func (t *Transport) Setup(ctx context.Context, settings transport.Settings) error {
   113  	t.ctx = ctx
   114  	t.settings = settings
   115  	return nil
   116  }
   117  
   118  // Init repository
   119  func (t *Transport) Init() (err error) {
   120  	if t.repository, err = git.PlainInit(t.settings.WorkDir, false); err != nil {
   121  		return errwrap.Wrapf("cannot create repository: {{err}}", err)
   122  	}
   123  
   124  	if t.worktree, err = t.repository.Worktree(); err != nil {
   125  		return errwrap.Wrapf("cannot create worktree: {{err}}", err)
   126  	}
   127  
   128  	return nil
   129  }
   130  
   131  func (t *Transport) getGitRemote() string {
   132  	var remote = t.settings.ConfigContext.Remote()
   133  
   134  	// always add a "wedeploy-" prefix to all deployment remote endpoints, but "lcp"
   135  	if remote != "lcp" {
   136  		remote = "lcp" + "-" + remote
   137  	}
   138  
   139  	return remote
   140  }
   141  
   142  // ProcessIgnored gets what file should be ignored.
   143  func (t *Transport) ProcessIgnored() (map[string]struct{}, error) {
   144  	i := ignoreChecker{
   145  		path: t.settings.Path,
   146  	}
   147  
   148  	return i.Process()
   149  }
   150  
   151  // AddRemote on project
   152  func (t *Transport) AddRemote() (err error) {
   153  	var gitServer = fmt.Sprintf("https://git.%v/%v.git",
   154  		t.settings.ConfigContext.InfrastructureDomain(),
   155  		t.settings.ProjectID)
   156  
   157  	_, err = t.repository.CreateRemote(&gitconfig.RemoteConfig{
   158  		Name: t.getGitRemote(),
   159  		URLs: []string{gitServer},
   160  	})
   161  
   162  	return err
   163  }
   164  
   165  // UserAgent of the transport layer.
   166  func (t *Transport) UserAgent() string {
   167  	return "go-git v4"
   168  }