diff --git a/pkg/tool/account.go b/pkg/tool/account.go index 1de8194..69d3810 100644 --- a/pkg/tool/account.go +++ b/pkg/tool/account.go @@ -17,12 +17,13 @@ package tool import ( "fmt" "net/http" + "net/url" "regexp" ) type AccountValidator struct{} -var repoDomainPattern = regexp.MustCompile("(?:https://(?:[^@:]+:[^@:]+@)?|git@)([^/:]+)") +var scpStylePattern = regexp.MustCompile("^(?:[^@]+@)?(?[^@/:]+):.+$") func (v AccountValidator) Validate(repoURL string, account string) error { domain, err := parseOutGitRepoDomain(repoURL) @@ -41,10 +42,15 @@ func (v AccountValidator) Validate(repoURL string, account string) error { } func parseOutGitRepoDomain(repoURL string) (string, error) { - // This works for GitHub, Bitbucket, and Gitlab - submatch := repoDomainPattern.FindStringSubmatch(repoURL) - if len(submatch) < 2 { - return "", fmt.Errorf("could not parse git repository domain for %q", repoURL) + // Git remotes can be either URLs or scp style remotes + parsedURL, err := url.Parse(repoURL) + + if err != nil || len(parsedURL.Hostname()) < 1 { + submatch := scpStylePattern.FindStringSubmatch(repoURL) + if len(submatch) < 2 || len(submatch[1]) < 1 { + return "", fmt.Errorf("could not parse git repository domain for %q", repoURL) + } + return submatch[1], nil } - return submatch[1], nil + return parsedURL.Hostname(), nil } diff --git a/pkg/tool/account_test.go b/pkg/tool/account_test.go index 30a03f5..ce2ff2d 100644 --- a/pkg/tool/account_test.go +++ b/pkg/tool/account_test.go @@ -15,6 +15,9 @@ func TestParseOutGitDomain(t *testing.T) { err error }{ {"GitHub SSH", "git@github.com:foo/bar", "github.com", nil}, + {"GitHub SSH 2", "ssh://github.com/foo/bar", "github.com", nil}, + {"GitHub SSH 3", "ssh://git@github.com:2222/foo/bar", "github.com", nil}, + {"GitHub SSH 4", "ssh://github.com:2222/foo/bar", "github.com", nil}, {"GitHub HTTPS", "https://github.com/foo/bar", "github.com", nil}, {"GitHub HTTPS with username/password", "https://foo:token@github.com/foo/bar", "github.com", nil}, {"Gitlab SSH", "git@gitlab.com:foo/bar", "gitlab.com", nil}, @@ -23,13 +26,15 @@ func TestParseOutGitDomain(t *testing.T) { {"Bitbucket SSH", "git@bitbucket.com:foo/bar", "bitbucket.com", nil}, {"Bitbucket HTTPS", "https://bitbucket.com/foo/bar", "bitbucket.com", nil}, {"Bitbucket HTTPS with username/password", "https://user:pass@bitbucket.com/foo/bar", "bitbucket.com", nil}, - {"Invalid", "foo/bar", "", fmt.Errorf("could not parse git repository domain for \"foo/bar\"")}, + {"Domain name without dot", "foo/bar", "", fmt.Errorf("could not parse git repository domain for \"foo/bar\"")}, + {"Domain name without dot 2", "foo/some/path/bar.git", "", fmt.Errorf("could not parse git repository domain for \"foo/some/path/bar.git\"")}, + {"Invalid", "user@:2222/bar", "", fmt.Errorf("could not parse git repository domain for \"user@:2222/bar\"")}, } for _, testData := range testDataSlice { t.Run(testData.name, func(t *testing.T) { actual, err := parseOutGitRepoDomain(testData.repoURL) - assert.Equal(t, err, testData.err) + assert.Equal(t, testData.err, err) assert.Equal(t, testData.expected, actual) }) }