Skip to content

Commit

Permalink
[fix] split query param to ref|tag|sha (#98)
Browse files Browse the repository at this point in the history
* split query param to ref|tag|sha
  • Loading branch information
ATGardner authored Jun 15, 2021
1 parent d436d76 commit b92a7ae
Show file tree
Hide file tree
Showing 10 changed files with 375 additions and 474 deletions.
4 changes: 1 addition & 3 deletions cmd/commands/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ func setAppOptsDefaults(ctx context.Context, repofs fs.FS, opts *AppCreateOption
// local directory
fsys = fs.Create(osfs.New(opts.AppOpts.AppSpecifier))
} else {
host, orgRepo, p, _, _, _, _ := util.ParseGitUrl(opts.AppOpts.AppSpecifier)
url := host + orgRepo
log.G().Infof("cloning repo: '%s', to infer app type from path '%s'", url, p)
log.G().Infof("trying to infer application type from '%s'", opts.AppOpts.AppSpecifier)
cloneOpts := &git.CloneOptions{
Repo: opts.AppOpts.AppSpecifier,
Auth: opts.CloneOpts.Auth,
Expand Down
3 changes: 2 additions & 1 deletion cmd/commands/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func NewRepoBootstrapCommand() *cobra.Command {
<BIN> repo bootstrap --repo https://github.com/example/repo/path/to/installation_root
`),
PreRun: func(cmd *cobra.Command, args []string) { cloneOpts.Parse() },
PreRun: func(_ *cobra.Command, _ []string) { cloneOpts.Parse() },
RunE: func(cmd *cobra.Command, args []string) error {
return RunRepoBootstrap(cmd.Context(), &RepoBootstrapOptions{
AppSpecifier: appSpecifier,
Expand Down Expand Up @@ -264,6 +264,7 @@ func RunRepoCreate(ctx context.Context, opts *RepoCreateOptions) (*git.CloneOpti
Password: opts.Token,
},
}

co.Parse()
return co, nil
}
Expand Down
9 changes: 4 additions & 5 deletions cmd/commands/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestRunRepoCreate(t *testing.T) {
Repo: "https://github.com/owner/name/path?ref=revision",
}
expected.Parse()
assert.Equal(t, "https://github.com/owner/name", cloneOpts.URL())
assert.Equal(t, "https://github.com/owner/name.git", cloneOpts.URL())
assert.Equal(t, "revision", cloneOpts.Revision())
assert.Equal(t, "path", cloneOpts.Path())
mp.AssertCalled(t, "CreateRepository", mock.Anything, mock.Anything)
Expand Down Expand Up @@ -247,7 +247,7 @@ func Test_buildBootstrapManifests(t *testing.T) {

argocdApp := &argocdv1alpha1.Application{}
assert.NoError(t, yaml.Unmarshal(b.argocdApp, argocdApp))
assert.Equal(t, "https://github.com/foo/bar", argocdApp.Spec.Source.RepoURL)
assert.Equal(t, "https://github.com/foo/bar.git", argocdApp.Spec.Source.RepoURL)
assert.Equal(t, filepath.Join("installation1", store.Default.BootsrtrapDir, store.Default.ArgoCDName), argocdApp.Spec.Source.Path)
assert.Equal(t, "main", argocdApp.Spec.Source.TargetRevision)
assert.Equal(t, 0, len(argocdApp.ObjectMeta.Finalizers))
Expand All @@ -256,7 +256,7 @@ func Test_buildBootstrapManifests(t *testing.T) {

bootstrapApp := &argocdv1alpha1.Application{}
assert.NoError(t, yaml.Unmarshal(b.bootstrapApp, bootstrapApp))
assert.Equal(t, "https://github.com/foo/bar", bootstrapApp.Spec.Source.RepoURL)
assert.Equal(t, "https://github.com/foo/bar.git", bootstrapApp.Spec.Source.RepoURL)
assert.Equal(t, filepath.Join("installation1", store.Default.BootsrtrapDir), bootstrapApp.Spec.Source.Path)
assert.Equal(t, "main", bootstrapApp.Spec.Source.TargetRevision)
assert.NotEqual(t, 0, len(bootstrapApp.ObjectMeta.Finalizers))
Expand All @@ -265,7 +265,7 @@ func Test_buildBootstrapManifests(t *testing.T) {

rootApp := &argocdv1alpha1.Application{}
assert.NoError(t, yaml.Unmarshal(b.rootApp, rootApp))
assert.Equal(t, "https://github.com/foo/bar", rootApp.Spec.Source.RepoURL)
assert.Equal(t, "https://github.com/foo/bar.git", rootApp.Spec.Source.RepoURL)
assert.Equal(t, filepath.Join("installation1", store.Default.ProjectsDir), rootApp.Spec.Source.Path)
assert.Equal(t, "main", rootApp.Spec.Source.TargetRevision)
assert.NotEqual(t, 0, len(rootApp.ObjectMeta.Finalizers))
Expand Down Expand Up @@ -296,7 +296,6 @@ func Test_buildBootstrapManifests(t *testing.T) {
for tname, tt := range tests {
t.Run(tname, func(t *testing.T) {
tt.args.cloneOpts.Parse()

b, ret := buildBootstrapManifests(
tt.args.namespace,
tt.args.appSpecifier,
Expand Down
15 changes: 8 additions & 7 deletions pkg/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import (
"reflect"

"github.com/argoproj-labs/argocd-autopilot/pkg/fs"
"github.com/argoproj-labs/argocd-autopilot/pkg/git"
"github.com/argoproj-labs/argocd-autopilot/pkg/kube"
"github.com/argoproj-labs/argocd-autopilot/pkg/log"
"github.com/argoproj-labs/argocd-autopilot/pkg/store"
"github.com/argoproj-labs/argocd-autopilot/pkg/util"

"github.com/ghodss/yaml"
billyUtils "github.com/go-git/go-billy/v5/util"
Expand Down Expand Up @@ -388,17 +388,18 @@ func newDirApp(opts *CreateOptions) *dirApp {
app := &dirApp{
baseApp: baseApp{opts},
}

host, orgRepo, path, gitRef, _, _, _ := util.ParseGitUrl(opts.AppSpecifier)
url := host + orgRepo
cloneOpts := &git.CloneOptions{
Repo: opts.AppSpecifier,
}
cloneOpts.Parse()
app.config = &Config{
AppName: opts.AppName,
UserGivenName: opts.AppName,
DestNamespace: opts.DestNamespace,
DestServer: opts.DestServer,
SrcRepoURL: url,
SrcPath: path,
SrcTargetRevision: gitRef,
SrcRepoURL: cloneOpts.URL(),
SrcPath: cloneOpts.Path(),
SrcTargetRevision: cloneOpts.Revision(),
}

return app
Expand Down
2 changes: 1 addition & 1 deletion pkg/application/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ func Test_newDirApp(t *testing.T) {
UserGivenName: "fooapp",
DestNamespace: "fizz",
DestServer: "buzz",
SrcRepoURL: "https://github.com/foo/bar",
SrcRepoURL: "https://github.com/foo/bar.git",
SrcTargetRevision: "v0.1.2",
SrcPath: "somepath/in/repo",
},
Expand Down
144 changes: 140 additions & 4 deletions pkg/git/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"net/url"
"os"
"strings"

Expand Down Expand Up @@ -57,6 +58,11 @@ type (
}
)

const (
gitSuffix = ".git"
gitDelimiter = "_git/"
)

// Errors
var (
ErrNilOpts = errors.New("options cannot be nil")
Expand Down Expand Up @@ -113,10 +119,11 @@ func (o *CloneOptions) Parse() {
var (
host string
orgRepo string
suffix string
)

host, orgRepo, o.path, o.revision, _, _, _ = util.ParseGitUrl(o.Repo)
o.url = host + orgRepo
host, orgRepo, o.path, o.revision, suffix = parseGitUrl(o.Repo)
o.url = host + orgRepo + suffix
}

func (o *CloneOptions) Clone(ctx context.Context) (Repository, fs.FS, error) {
Expand Down Expand Up @@ -153,7 +160,7 @@ func (o *CloneOptions) URL() string {
}

func (o *CloneOptions) Revision() string {
return o.revision
return plumbing.ReferenceName(o.revision).Short()
}

func (o *CloneOptions) Path() string {
Expand Down Expand Up @@ -208,7 +215,7 @@ var clone = func(ctx context.Context, opts *CloneOptions) (*repo, error) {
}

if opts.revision != "" {
cloneOpts.ReferenceName = plumbing.NewBranchReferenceName(opts.revision)
cloneOpts.ReferenceName = plumbing.ReferenceName(opts.revision)
}

log.G(ctx).WithFields(log.Fields{
Expand Down Expand Up @@ -280,3 +287,132 @@ func getAuth(auth Auth) transport.AuthMethod {
Password: auth.Password,
}
}

// From strings like [email protected]:someOrg/someRepo.git or
// https://github.com/someOrg/someRepo?ref=someHash, extract
// the parts.
func parseGitUrl(n string) (host, orgRepo, path, ref, gitSuff string) {
if strings.Contains(n, gitDelimiter) {
index := strings.Index(n, gitDelimiter)
// Adding _git/ to host
host = normalizeGitHostSpec(n[:index+len(gitDelimiter)])
orgRepo = strings.Split(strings.Split(n[index+len(gitDelimiter):], "/")[0], "?")[0]
path, ref = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):])
return
}

host, n = parseHostSpec(n)
gitSuff = gitSuffix
if strings.Contains(n, gitSuffix) {
index := strings.Index(n, gitSuffix)
orgRepo = n[0:index]
n = n[index+len(gitSuffix):]
path, ref = peelQuery(n)
return
}

i := strings.Index(n, "/")
if i < 1 {
path, ref = peelQuery(n)
return
}

j := strings.Index(n[i+1:], "/")
if j >= 0 {
j += i + 1
orgRepo = n[:j]
path, ref = peelQuery(n[j+1:])
return
}

path = ""
orgRepo, ref = peelQuery(n)
return
}

func peelQuery(arg string) (path, ref string) {
parsed, err := url.Parse(arg)
if err != nil {
return path, ""
}

path = parsed.Path
values := parsed.Query()
branch := values.Get("ref")
tag := values.Get("tag")
sha := values.Get("sha")
if sha != "" {
ref = sha
return
}

if tag != "" {
ref = "refs/tags/" + tag
return
}

if branch != "" {
ref = "refs/heads/" + branch
return
}

return
}

func parseHostSpec(n string) (string, string) {
var host string
// Start accumulating the host part.
for _, p := range [...]string{
// Order matters here.
"git::", "gh:", "ssh://", "https://", "http://",
"git@", "github.com:", "github.com/"} {
if len(p) < len(n) && strings.ToLower(n[:len(p)]) == p {
n = n[len(p):]
host += p
}
}
if host == "git@" {
i := strings.Index(n, "/")
if i > -1 {
host += n[:i+1]
n = n[i+1:]
} else {
i = strings.Index(n, ":")
if i > -1 {
host += n[:i+1]
n = n[i+1:]
}
}
return host, n
}

// If host is a http(s) or ssh URL, grab the domain part.
for _, p := range [...]string{
"ssh://", "https://", "http://"} {
if strings.HasSuffix(host, p) {
i := strings.Index(n, "/")
if i > -1 {
host = host + n[0:i+1]
n = n[i+1:]
}
break
}
}

return normalizeGitHostSpec(host), n
}

func normalizeGitHostSpec(host string) string {
s := strings.ToLower(host)
if strings.Contains(s, "github.com") {
if strings.Contains(s, "git@") || strings.Contains(s, "ssh:") {
host = "[email protected]:"
} else {
host = "https://github.com/"
}
}
if strings.HasPrefix(s, "git::") {
host = strings.TrimPrefix(s, "git::")
}
return host
}
8 changes: 4 additions & 4 deletions pkg/git/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ func Test_clone(t *testing.T) {
Repo: "https://github.com/owner/name",
},
expectedOpts: &gg.CloneOptions{
URL: "https://github.com/owner/name",
URL: "https://github.com/owner/name.git",
Auth: nil,
Depth: 1,
Progress: os.Stderr,
Expand All @@ -266,7 +266,7 @@ func Test_clone(t *testing.T) {
},
},
expectedOpts: &gg.CloneOptions{
URL: "https://github.com/owner/name",
URL: "https://github.com/owner/name.git",
Auth: &http.BasicAuth{
Username: "asd",
Password: "123",
Expand All @@ -284,7 +284,7 @@ func Test_clone(t *testing.T) {
Repo: "https://github.com/owner/name",
},
expectedOpts: &gg.CloneOptions{
URL: "https://github.com/owner/name",
URL: "https://github.com/owner/name.git",
Depth: 1,
Progress: os.Stderr,
Tags: gg.NoTags,
Expand All @@ -300,7 +300,7 @@ func Test_clone(t *testing.T) {
Repo: "https://github.com/owner/name?ref=test",
},
expectedOpts: &gg.CloneOptions{
URL: "https://github.com/owner/name",
URL: "https://github.com/owner/name.git",
Depth: 1,
Progress: os.Stderr,
Tags: gg.NoTags,
Expand Down
Loading

0 comments on commit b92a7ae

Please sign in to comment.