Initial commit with support for GitHub actions
This commit is contained in:
144
common/draw.go
Normal file
144
common/draw.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Style is a specific style
|
||||
type Style int
|
||||
|
||||
// Styles
|
||||
const (
|
||||
StyleDoubleLine = iota
|
||||
StyleSingleLine
|
||||
StyleDashedLine
|
||||
StyleNoLine
|
||||
)
|
||||
|
||||
// NewPen creates a new pen
|
||||
func NewPen(style Style, color int) *Pen {
|
||||
bgcolor := 49
|
||||
if os.Getenv("CLICOLOR") == "0" {
|
||||
color = 0
|
||||
bgcolor = 0
|
||||
}
|
||||
return &Pen{
|
||||
style: style,
|
||||
color: color,
|
||||
bgcolor: bgcolor,
|
||||
}
|
||||
}
|
||||
|
||||
type styleDef struct {
|
||||
cornerTL string
|
||||
cornerTR string
|
||||
cornerBL string
|
||||
cornerBR string
|
||||
lineH string
|
||||
lineV string
|
||||
}
|
||||
|
||||
var styleDefs = []styleDef{
|
||||
{"\u2554", "\u2557", "\u255a", "\u255d", "\u2550", "\u2551"},
|
||||
//{"\u250c", "\u2510", "\u2514", "\u2518", "\u2500", "\u2502"},
|
||||
{"\u256d", "\u256e", "\u2570", "\u256f", "\u2500", "\u2502"},
|
||||
{"\u250c", "\u2510", "\u2514", "\u2518", "\u254c", "\u254e"},
|
||||
{" ", " ", " ", " ", " ", " "},
|
||||
}
|
||||
|
||||
// Pen struct
|
||||
type Pen struct {
|
||||
style Style
|
||||
color int
|
||||
bgcolor int
|
||||
}
|
||||
|
||||
// Drawing struct
|
||||
type Drawing struct {
|
||||
buf *strings.Builder
|
||||
width int
|
||||
}
|
||||
|
||||
func (p *Pen) drawTopBars(buf io.Writer, labels ...string) {
|
||||
style := styleDefs[p.style]
|
||||
for _, label := range labels {
|
||||
bar := strings.Repeat(style.lineH, len(label)+2)
|
||||
fmt.Fprintf(buf, " ")
|
||||
fmt.Fprintf(buf, "\x1b[%d;%dm", p.color, p.bgcolor)
|
||||
fmt.Fprintf(buf, "%s%s%s", style.cornerTL, bar, style.cornerTR)
|
||||
fmt.Fprintf(buf, "\x1b[%dm", 0)
|
||||
}
|
||||
fmt.Fprintf(buf, "\n")
|
||||
}
|
||||
func (p *Pen) drawBottomBars(buf io.Writer, labels ...string) {
|
||||
style := styleDefs[p.style]
|
||||
for _, label := range labels {
|
||||
bar := strings.Repeat(style.lineH, len(label)+2)
|
||||
fmt.Fprintf(buf, " ")
|
||||
fmt.Fprintf(buf, "\x1b[%d;%dm", p.color, p.bgcolor)
|
||||
fmt.Fprintf(buf, "%s%s%s", style.cornerBL, bar, style.cornerBR)
|
||||
fmt.Fprintf(buf, "\x1b[%dm", 0)
|
||||
}
|
||||
fmt.Fprintf(buf, "\n")
|
||||
}
|
||||
func (p *Pen) drawLabels(buf io.Writer, labels ...string) {
|
||||
style := styleDefs[p.style]
|
||||
for _, label := range labels {
|
||||
fmt.Fprintf(buf, " ")
|
||||
fmt.Fprintf(buf, "\x1b[%d;%dm", p.color, p.bgcolor)
|
||||
fmt.Fprintf(buf, "%s %s %s", style.lineV, label, style.lineV)
|
||||
fmt.Fprintf(buf, "\x1b[%dm", 0)
|
||||
}
|
||||
fmt.Fprintf(buf, "\n")
|
||||
}
|
||||
|
||||
// DrawArrow between boxes
|
||||
func (p *Pen) DrawArrow() *Drawing {
|
||||
drawing := &Drawing{
|
||||
buf: new(strings.Builder),
|
||||
width: 1,
|
||||
}
|
||||
fmt.Fprintf(drawing.buf, "\x1b[%dm", p.color)
|
||||
fmt.Fprintf(drawing.buf, "\u2b07")
|
||||
fmt.Fprintf(drawing.buf, "\x1b[%dm", 0)
|
||||
return drawing
|
||||
}
|
||||
|
||||
// DrawBoxes to draw boxes
|
||||
func (p *Pen) DrawBoxes(labels ...string) *Drawing {
|
||||
width := 0
|
||||
for _, l := range labels {
|
||||
width += len(l) + 2 + 2 + 1
|
||||
}
|
||||
drawing := &Drawing{
|
||||
buf: new(strings.Builder),
|
||||
width: width,
|
||||
}
|
||||
p.drawTopBars(drawing.buf, labels...)
|
||||
p.drawLabels(drawing.buf, labels...)
|
||||
p.drawBottomBars(drawing.buf, labels...)
|
||||
|
||||
return drawing
|
||||
}
|
||||
|
||||
// Draw to writer
|
||||
func (d *Drawing) Draw(writer io.Writer, centerOnWidth int) {
|
||||
padSize := (centerOnWidth - d.GetWidth()) / 2
|
||||
if padSize < 0 {
|
||||
padSize = 0
|
||||
}
|
||||
for _, l := range strings.Split(d.buf.String(), "\n") {
|
||||
if len(l) > 0 {
|
||||
padding := strings.Repeat(" ", padSize)
|
||||
fmt.Fprintf(writer, "%s%s\n", padding, l)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetWidth of drawing
|
||||
func (d *Drawing) GetWidth() int {
|
||||
return d.width
|
||||
}
|
100
common/executor.go
Normal file
100
common/executor.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Warning that implements `error` but safe to ignore
|
||||
type Warning struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
// Error the contract for error
|
||||
func (w Warning) Error() string {
|
||||
return w.Message
|
||||
}
|
||||
|
||||
// Warningf create a warning
|
||||
func Warningf(format string, args ...interface{}) Warning {
|
||||
w := Warning{
|
||||
Message: fmt.Sprintf(format, args...),
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
// Executor define contract for the steps of a workflow
|
||||
type Executor func() error
|
||||
|
||||
// Conditional define contract for the conditional predicate
|
||||
type Conditional func() bool
|
||||
|
||||
// NewPipelineExecutor creates a new executor from a series of other executors
|
||||
func NewPipelineExecutor(executors ...Executor) Executor {
|
||||
return func() error {
|
||||
for _, executor := range executors {
|
||||
if executor == nil {
|
||||
continue
|
||||
}
|
||||
err := executor()
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case Warning:
|
||||
log.Warning(err.Error())
|
||||
return nil
|
||||
default:
|
||||
log.Debugf("%+v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// NewConditionalExecutor creates a new executor based on conditions
|
||||
func NewConditionalExecutor(conditional Conditional, trueExecutor Executor, falseExecutor Executor) Executor {
|
||||
return func() error {
|
||||
if conditional() {
|
||||
if trueExecutor != nil {
|
||||
return trueExecutor()
|
||||
}
|
||||
} else {
|
||||
if falseExecutor != nil {
|
||||
return falseExecutor()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func executeWithChan(executor Executor, errChan chan error) {
|
||||
errChan <- executor()
|
||||
}
|
||||
|
||||
// NewErrorExecutor creates a new executor that always errors out
|
||||
func NewErrorExecutor(err error) Executor {
|
||||
return func() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// NewParallelExecutor creates a new executor from a parallel of other executors
|
||||
func NewParallelExecutor(executors ...Executor) Executor {
|
||||
return func() error {
|
||||
errChan := make(chan error)
|
||||
|
||||
for _, executor := range executors {
|
||||
go executeWithChan(executor, errChan)
|
||||
}
|
||||
|
||||
for i := 0; i < len(executors); i++ {
|
||||
err := <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
84
common/executor_test.go
Normal file
84
common/executor_test.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewWorkflow(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// empty
|
||||
emptyWorkflow := NewPipelineExecutor()
|
||||
assert.Nil(emptyWorkflow())
|
||||
|
||||
// error case
|
||||
errorWorkflow := NewErrorExecutor(fmt.Errorf("test error"))
|
||||
assert.NotNil(errorWorkflow())
|
||||
|
||||
// multiple success case
|
||||
runcount := 0
|
||||
successWorkflow := NewPipelineExecutor(
|
||||
func() error {
|
||||
runcount = runcount + 1
|
||||
return nil
|
||||
},
|
||||
func() error {
|
||||
runcount = runcount + 1
|
||||
return nil
|
||||
})
|
||||
assert.Nil(successWorkflow())
|
||||
assert.Equal(2, runcount)
|
||||
}
|
||||
|
||||
func TestNewConditionalExecutor(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
trueCount := 0
|
||||
falseCount := 0
|
||||
|
||||
err := NewConditionalExecutor(func() bool {
|
||||
return false
|
||||
}, func() error {
|
||||
trueCount++
|
||||
return nil
|
||||
}, func() error {
|
||||
falseCount++
|
||||
return nil
|
||||
})()
|
||||
|
||||
assert.Nil(err)
|
||||
assert.Equal(0, trueCount)
|
||||
assert.Equal(1, falseCount)
|
||||
|
||||
err = NewConditionalExecutor(func() bool {
|
||||
return true
|
||||
}, func() error {
|
||||
trueCount++
|
||||
return nil
|
||||
}, func() error {
|
||||
falseCount++
|
||||
return nil
|
||||
})()
|
||||
|
||||
assert.Nil(err)
|
||||
assert.Equal(1, trueCount)
|
||||
assert.Equal(1, falseCount)
|
||||
}
|
||||
|
||||
func TestNewParallelExecutor(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
count := 0
|
||||
emptyWorkflow := NewPipelineExecutor(func() error {
|
||||
count++
|
||||
return nil
|
||||
})
|
||||
|
||||
err := NewParallelExecutor(emptyWorkflow, emptyWorkflow)()
|
||||
assert.Equal(2, count)
|
||||
|
||||
assert.Nil(err)
|
||||
}
|
79
common/file.go
Normal file
79
common/file.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// CopyFile copy file
|
||||
func CopyFile(source string, dest string) (err error) {
|
||||
sourcefile, err := os.Open(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer sourcefile.Close()
|
||||
|
||||
destfile, err := os.Create(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer destfile.Close()
|
||||
|
||||
_, err = io.Copy(destfile, sourcefile)
|
||||
if err == nil {
|
||||
sourceinfo, err := os.Stat(source)
|
||||
if err != nil {
|
||||
_ = os.Chmod(dest, sourceinfo.Mode())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CopyDir recursive copy of directory
|
||||
func CopyDir(source string, dest string) (err error) {
|
||||
|
||||
// get properties of source dir
|
||||
sourceinfo, err := os.Stat(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create dest dir
|
||||
|
||||
err = os.MkdirAll(dest, sourceinfo.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
directory, _ := os.Open(source)
|
||||
|
||||
objects, err := directory.Readdir(-1)
|
||||
|
||||
for _, obj := range objects {
|
||||
|
||||
sourcefilepointer := source + "/" + obj.Name()
|
||||
|
||||
destinationfilepointer := dest + "/" + obj.Name()
|
||||
|
||||
if obj.IsDir() {
|
||||
// create sub-directories - recursively
|
||||
err = CopyDir(sourcefilepointer, destinationfilepointer)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
// perform copy
|
||||
err = CopyFile(sourcefilepointer, destinationfilepointer)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
219
common/git.go
Normal file
219
common/git.go
Normal file
@@ -0,0 +1,219 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/go-ini/ini"
|
||||
log "github.com/sirupsen/logrus"
|
||||
git "gopkg.in/src-d/go-git.v4"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var cloneLock sync.Mutex
|
||||
|
||||
// FindGitRevision get the current git revision
|
||||
func FindGitRevision(file string) (shortSha string, sha string, err error) {
|
||||
gitDir, err := findGitDirectory(file)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
head, err := findGitHead(file)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
// load commitid ref
|
||||
refBuf, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gitDir, head))
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return string(string(refBuf)[:7]), string(refBuf), nil
|
||||
}
|
||||
|
||||
// FindGitBranch get the current git branch
|
||||
func FindGitBranch(file string) (string, error) {
|
||||
head, err := findGitHead(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// get branch name
|
||||
branch := strings.TrimPrefix(head, "refs/heads/")
|
||||
log.Debugf("Found branch: %s", branch)
|
||||
return branch, nil
|
||||
}
|
||||
|
||||
func findGitHead(file string) (string, error) {
|
||||
gitDir, err := findGitDirectory(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
log.Debugf("Loading revision from git directory '%s'", gitDir)
|
||||
|
||||
// load HEAD ref
|
||||
headFile, err := os.Open(fmt.Sprintf("%s/HEAD", gitDir))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer func() {
|
||||
headFile.Close()
|
||||
}()
|
||||
|
||||
headBuffer := new(bytes.Buffer)
|
||||
headBuffer.ReadFrom(bufio.NewReader(headFile))
|
||||
head := make(map[string]string)
|
||||
yaml.Unmarshal(headBuffer.Bytes(), head)
|
||||
|
||||
log.Debugf("HEAD points to '%s'", head["ref"])
|
||||
|
||||
return head["ref"], nil
|
||||
}
|
||||
|
||||
// FindGithubRepo get the repo
|
||||
func FindGithubRepo(file string) (string, error) {
|
||||
url, err := findGitRemoteURL(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, slug, err := findGitSlug(url)
|
||||
return slug, err
|
||||
}
|
||||
|
||||
func findGitRemoteURL(file string) (string, error) {
|
||||
gitDir, err := findGitDirectory(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
log.Debugf("Loading slug from git directory '%s'", gitDir)
|
||||
|
||||
gitconfig, err := ini.InsensitiveLoad(fmt.Sprintf("%s/config", gitDir))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
remote, err := gitconfig.GetSection("remote \"origin\"")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
urlKey, err := remote.GetKey("url")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
url := urlKey.String()
|
||||
return url, nil
|
||||
}
|
||||
|
||||
func findGitSlug(url string) (string, string, error) {
|
||||
codeCommitHTTPRegex := regexp.MustCompile(`^http(s?)://git-codecommit\.(.+)\.amazonaws.com/v1/repos/(.+)$`)
|
||||
codeCommitSSHRegex := regexp.MustCompile(`ssh://git-codecommit\.(.+)\.amazonaws.com/v1/repos/(.+)$`)
|
||||
httpRegex := regexp.MustCompile("^http(s?)://.*github.com.*/(.+)/(.+).git$")
|
||||
sshRegex := regexp.MustCompile("github.com:(.+)/(.+).git$")
|
||||
|
||||
if matches := codeCommitHTTPRegex.FindStringSubmatch(url); matches != nil {
|
||||
return "CodeCommit", matches[3], nil
|
||||
} else if matches := codeCommitSSHRegex.FindStringSubmatch(url); matches != nil {
|
||||
return "CodeCommit", matches[2], nil
|
||||
} else if matches := httpRegex.FindStringSubmatch(url); matches != nil {
|
||||
return "GitHub", fmt.Sprintf("%s/%s", matches[2], matches[3]), nil
|
||||
} else if matches := sshRegex.FindStringSubmatch(url); matches != nil {
|
||||
return "GitHub", fmt.Sprintf("%s/%s", matches[1], matches[2]), nil
|
||||
}
|
||||
return "", url, nil
|
||||
}
|
||||
|
||||
func findGitDirectory(fromFile string) (string, error) {
|
||||
absPath, err := filepath.Abs(fromFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Debugf("Searching for git directory in %s", absPath)
|
||||
fi, err := os.Stat(absPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var dir string
|
||||
if fi.Mode().IsDir() {
|
||||
dir = absPath
|
||||
} else {
|
||||
dir = path.Dir(absPath)
|
||||
}
|
||||
|
||||
gitPath := path.Join(dir, ".git")
|
||||
fi, err = os.Stat(gitPath)
|
||||
if err == nil && fi.Mode().IsDir() {
|
||||
return gitPath, nil
|
||||
} else if dir == "/" || dir == "C:\\" || dir == "c:\\" {
|
||||
return "", errors.New("unable to find git repo")
|
||||
}
|
||||
|
||||
return findGitDirectory(filepath.Dir(dir))
|
||||
|
||||
}
|
||||
|
||||
// NewGitCloneExecutorInput the input for the NewGitCloneExecutor
|
||||
type NewGitCloneExecutorInput struct {
|
||||
URL *url.URL
|
||||
Ref string
|
||||
Dir string
|
||||
Logger *log.Entry
|
||||
Dryrun bool
|
||||
}
|
||||
|
||||
// NewGitCloneExecutor creates an executor to clone git repos
|
||||
func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor {
|
||||
return func() error {
|
||||
input.Logger.Infof("git clone '%s'", input.URL.String())
|
||||
input.Logger.Debugf(" cloning %s to %s", input.URL.String(), input.Dir)
|
||||
|
||||
if input.Dryrun {
|
||||
return nil
|
||||
}
|
||||
|
||||
cloneLock.Lock()
|
||||
defer cloneLock.Unlock()
|
||||
|
||||
r, err := git.PlainOpen(input.Dir)
|
||||
if err != nil {
|
||||
r, err = git.PlainClone(input.Dir, false, &git.CloneOptions{
|
||||
URL: input.URL.String(),
|
||||
Progress: input.Logger.WriterLevel(log.DebugLevel),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
w, err := r.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.Pull(&git.PullOptions{})
|
||||
input.Logger.Debugf("Cloned %s to %s", input.URL.String(), input.Dir)
|
||||
|
||||
err = w.Checkout(&git.CheckoutOptions{
|
||||
//Branch: plumbing.NewHash(ref),
|
||||
Hash: plumbing.NewHash(input.Ref),
|
||||
})
|
||||
if err != nil {
|
||||
input.Logger.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
input.Logger.Debugf("Checked out %s", input.Ref)
|
||||
return nil
|
||||
}
|
||||
}
|
75
common/git_test.go
Normal file
75
common/git_test.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFindGitSlug(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var slugTests = []struct {
|
||||
url string // input
|
||||
provider string // expected result
|
||||
slug string // expected result
|
||||
}{
|
||||
{"https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo-name", "CodeCommit", "my-repo-name"},
|
||||
{"ssh://git-codecommit.us-west-2.amazonaws.com/v1/repos/my-repo", "CodeCommit", "my-repo"},
|
||||
{"git@github.com:nektos/act.git", "GitHub", "nektos/act"},
|
||||
{"https://github.com/nektos/act.git", "GitHub", "nektos/act"},
|
||||
{"http://github.com/nektos/act.git", "GitHub", "nektos/act"},
|
||||
{"http://myotherrepo.com/act.git", "", "http://myotherrepo.com/act.git"},
|
||||
}
|
||||
|
||||
for _, tt := range slugTests {
|
||||
provider, slug, err := findGitSlug(tt.url)
|
||||
|
||||
assert.Nil(err)
|
||||
assert.Equal(tt.provider, provider)
|
||||
assert.Equal(tt.slug, slug)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFindGitRemoteURL(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
basedir, err := ioutil.TempDir("", "act-test")
|
||||
defer os.RemoveAll(basedir)
|
||||
|
||||
assert.Nil(err)
|
||||
|
||||
err = gitCmd("init", basedir)
|
||||
assert.Nil(err)
|
||||
|
||||
remoteURL := "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo-name"
|
||||
err = gitCmd("config", "-f", fmt.Sprintf("%s/.git/config", basedir), "--add", "remote.origin.url", remoteURL)
|
||||
assert.Nil(err)
|
||||
|
||||
u, err := findGitRemoteURL(basedir)
|
||||
assert.Nil(err)
|
||||
assert.Equal(remoteURL, u)
|
||||
}
|
||||
|
||||
func gitCmd(args ...string) error {
|
||||
var stdout bytes.Buffer
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = ioutil.Discard
|
||||
|
||||
err := cmd.Run()
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
if waitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok {
|
||||
return fmt.Errorf("Exit error %d", waitStatus.ExitStatus())
|
||||
}
|
||||
return exitError
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user