Generic git checkout (#1951)

This commit is contained in:
Janos Dobronszki 2020-08-19 17:24:42 +02:00 committed by Vasiliy Tolstov
parent cf084b410f
commit eee5b98d78

View File

@ -19,6 +19,8 @@ import (
"github.com/xanzy/go-gitlab" "github.com/xanzy/go-gitlab"
) )
const credentialsKey = "GIT_CREDENTIALS"
type Gitter interface { type Gitter interface {
Checkout(repo, branchOrCommit string) error Checkout(repo, branchOrCommit string) error
RepoDir() string RepoDir() string
@ -43,15 +45,58 @@ func (g *binaryGitter) Checkout(repo, branchOrCommit string) error {
return g.checkoutGithub(repo, branchOrCommit) return g.checkoutGithub(repo, branchOrCommit)
} else if strings.Contains(repo, "gitlab") { } else if strings.Contains(repo, "gitlab") {
err := g.checkoutGitLabPublic(repo, branchOrCommit) err := g.checkoutGitLabPublic(repo, branchOrCommit)
if err != nil { if err != nil && len(g.secrets[credentialsKey]) > 0 {
// If the public download fails, try getting it with tokens. // If the public download fails, try getting it with tokens.
// Private downloads needs a token for api project listing, hence // Private downloads needs a token for api project listing, hence
// the weird structure of this code. // the weird structure of this code.
return g.checkoutGitLabPrivate(repo, branchOrCommit) return g.checkoutGitLabPrivate(repo, branchOrCommit)
} }
return nil return err
} }
return fmt.Errorf("Repo host %v is not supported yet", repo) if len(g.secrets[credentialsKey]) > 0 {
return g.checkoutAnyRemote(repo, branchOrCommit, true)
}
return g.checkoutAnyRemote(repo, branchOrCommit, false)
}
// This aims to be a generic checkout method. Currently only tested for bitbucket,
// see tests
func (g *binaryGitter) checkoutAnyRemote(repo, branchOrCommit string, useCredentials bool) error {
repoFolder := strings.ReplaceAll(strings.ReplaceAll(repo, "/", "-"), "https://", "")
g.folder = filepath.Join(os.TempDir(),
repoFolder+"-"+shortid.MustGenerate())
err := os.MkdirAll(g.folder, 0755)
if err != nil {
return err
}
// Assumes remote address format is git@gitlab.com:micro-test/monorepo-test.git
remoteAddr := fmt.Sprintf("https://%v", repo)
if useCredentials {
remoteAddr = fmt.Sprintf("https://%v@%v", g.secrets[credentialsKey], repo)
}
cmd := exec.Command("git", "clone", remoteAddr, "--depth=1", ".")
cmd.Dir = g.folder
outp, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("Git clone failed: %v", string(outp))
}
cmd = exec.Command("git", "fetch", "origin", branchOrCommit, "--depth=1")
cmd.Dir = g.folder
outp, err = cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("Git fetch failed: %v", string(outp))
}
cmd = exec.Command("git", "checkout", branchOrCommit)
cmd.Dir = g.folder
outp, err = cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("Git checkout failed: %v", string(outp))
}
return nil
} }
func (g *binaryGitter) checkoutGithub(repo, branchOrCommit string) error { func (g *binaryGitter) checkoutGithub(repo, branchOrCommit string) error {
@ -66,8 +111,8 @@ func (g *binaryGitter) checkoutGithub(repo, branchOrCommit string) error {
} }
client := &http.Client{} client := &http.Client{}
req, _ := http.NewRequest("GET", url, nil) req, _ := http.NewRequest("GET", url, nil)
if len(g.secrets["GIT_CREDENTIALS"]) > 0 { if len(g.secrets[credentialsKey]) > 0 {
req.Header.Set("Authorization", "token "+g.secrets["GIT_CREDENTIALS"]) req.Header.Set("Authorization", "token "+g.secrets[credentialsKey])
} }
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
@ -151,7 +196,7 @@ func (g *binaryGitter) checkoutGitLabPublic(repo, branchOrCommit string) error {
} }
func (g *binaryGitter) checkoutGitLabPrivate(repo, branchOrCommit string) error { func (g *binaryGitter) checkoutGitLabPrivate(repo, branchOrCommit string) error {
git, err := gitlab.NewClient(g.secrets["GIT_CREDENTIALS"]) git, err := gitlab.NewClient(g.secrets[credentialsKey])
if err != nil { if err != nil {
return err return err
} }
@ -173,7 +218,7 @@ func (g *binaryGitter) checkoutGitLabPrivate(repo, branchOrCommit string) error
} }
// Example URL: // Example URL:
// https://gitlab.com/api/v3/projects/0000000/repository/archive?private_token=XXXXXXXXXXXXXXXXXXXX // https://gitlab.com/api/v3/projects/0000000/repository/archive?private_token=XXXXXXXXXXXXXXXXXXXX
url := fmt.Sprintf("https://gitlab.com/api/v4/projects/%v/repository/archive?private_token=%v", projectID, g.secrets["GIT_CREDENTIALS"]) url := fmt.Sprintf("https://gitlab.com/api/v4/projects/%v/repository/archive?private_token=%v", projectID, g.secrets[credentialsKey])
client := &http.Client{} client := &http.Client{}
req, _ := http.NewRequest("GET", url, nil) req, _ := http.NewRequest("GET", url, nil)