Fix repo listing case for bitbucket (#720)

This commit is contained in:
Dan Wilson 2023-10-26 08:47:53 +00:00 committed by Harness
parent 6ee49f9848
commit b9b80197a4
2 changed files with 47 additions and 44 deletions

View File

@ -46,12 +46,6 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo
return nil, fmt.Errorf("failed to sanitize input: %w", err) return nil, fmt.Errorf("failed to sanitize input: %w", err)
} }
// Bitbucket access token authentication requires the literal substitution of x-token-auth
// in place of the username (ref: https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/).
if in.Provider.Type == importer.ProviderTypeBitbucket {
in.Provider.Username = "x-token-auth"
}
remoteRepository, err := importer.LoadRepositoryFromProvider(ctx, in.Provider, in.ProviderRepo) remoteRepository, err := importer.LoadRepositoryFromProvider(ctx, in.Provider, in.ProviderRepo)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -31,6 +31,7 @@ import (
"github.com/drone/go-scm/scm/driver/github" "github.com/drone/go-scm/scm/driver/github"
"github.com/drone/go-scm/scm/driver/gitlab" "github.com/drone/go-scm/scm/driver/gitlab"
"github.com/drone/go-scm/scm/driver/stash" "github.com/drone/go-scm/scm/driver/stash"
"github.com/drone/go-scm/scm/transport"
"github.com/drone/go-scm/scm/transport/oauth2" "github.com/drone/go-scm/scm/transport/oauth2"
) )
@ -98,30 +99,32 @@ func hash(s string) string {
return base32.StdEncoding.EncodeToString(h.Sum(nil)[:10]) return base32.StdEncoding.EncodeToString(h.Sum(nil)[:10])
} }
func getScmClientWithTransport(provider Provider, authReq bool) (*scm.Client, error) { func oauthTransport(token string) (http.RoundTripper, error) {
if authReq && (provider.Username == "" || provider.Password == "") { if token == "" {
return nil, usererror.BadRequest("scm provider authentication credentials missing") return nil, errors.New("no token provided")
} }
return &oauth2.Transport{
c, err := getScmClient(provider) Source: oauth2.StaticTokenSource(&scm.Token{Token: token}),
if err != nil { }, nil
return nil, usererror.BadRequestf("could not create scm client: %s", err)
}
if provider.Password != "" {
c.Client = &http.Client{
Transport: &oauth2.Transport{
Source: oauth2.StaticTokenSource(&scm.Token{Token: provider.Password}),
},
}
}
return c, nil
} }
func getScmClient(provider Provider) (*scm.Client, error) { //nolint:gocognit func basicAuthTransport(username, password string) (http.RoundTripper, error) {
if username == "" || password == "" {
return nil, errors.New("username or password not provided")
}
return &transport.BasicAuth{
Username: username,
Password: password,
}, nil
}
// getScmClientWithTransport creates an SCM client along with the necessary transport
// layer depending on the provider. For example, for bitbucket we support app passwords
// so the auth transport is BasicAuth whereas it's Oauth for other providers.
func getScmClientWithTransport(provider Provider) (*scm.Client, error) { //nolint:gocognit
var c *scm.Client var c *scm.Client
var err error var err, transportErr error
var transport http.RoundTripper
switch provider.Type { switch provider.Type {
case "": case "":
return nil, errors.New("scm provider can not be empty") return nil, errors.New("scm provider can not be empty")
@ -135,6 +138,7 @@ func getScmClient(provider Provider) (*scm.Client, error) { //nolint:gocognit
} else { } else {
c = github.NewDefault() c = github.NewDefault()
} }
transport, transportErr = oauthTransport(provider.Password)
case ProviderTypeGitLab: case ProviderTypeGitLab:
if provider.Host != "" { if provider.Host != "" {
@ -145,6 +149,7 @@ func getScmClient(provider Provider) (*scm.Client, error) { //nolint:gocognit
} else { } else {
c = gitlab.NewDefault() c = gitlab.NewDefault()
} }
transport, transportErr = oauthTransport(provider.Password)
case ProviderTypeBitbucket: case ProviderTypeBitbucket:
if provider.Host != "" { if provider.Host != "" {
@ -155,6 +160,7 @@ func getScmClient(provider Provider) (*scm.Client, error) { //nolint:gocognit
} else { } else {
c = bitbucket.NewDefault() c = bitbucket.NewDefault()
} }
transport, transportErr = basicAuthTransport(provider.Username, provider.Password)
case ProviderTypeStash: case ProviderTypeStash:
if provider.Host != "" { if provider.Host != "" {
@ -165,18 +171,25 @@ func getScmClient(provider Provider) (*scm.Client, error) { //nolint:gocognit
} else { } else {
c = stash.NewDefault() c = stash.NewDefault()
} }
transport, transportErr = oauthTransport(provider.Password)
default: default:
return nil, fmt.Errorf("unsupported scm provider: %s", provider) return nil, fmt.Errorf("unsupported scm provider: %s", provider)
} }
if transportErr != nil {
return nil, fmt.Errorf("could not create transport: %w", transportErr)
}
c.Client = &http.Client{Transport: transport}
return c, nil return c, nil
} }
func LoadRepositoryFromProvider(ctx context.Context, provider Provider, repoSlug string) (RepositoryInfo, error) { func LoadRepositoryFromProvider(ctx context.Context, provider Provider, repoSlug string) (RepositoryInfo, error) {
scmClient, err := getScmClientWithTransport(provider, false) scmClient, err := getScmClientWithTransport(provider)
if err != nil { if err != nil {
return RepositoryInfo{}, err return RepositoryInfo{}, usererror.BadRequestf("could not create client: %s", err)
} }
if repoSlug == "" { if repoSlug == "" {
@ -202,31 +215,20 @@ func LoadRepositoriesFromProviderSpace(
provider Provider, provider Provider,
spaceSlug string, spaceSlug string,
) ([]RepositoryInfo, error) { ) ([]RepositoryInfo, error) {
scmClient, err := getScmClientWithTransport(provider, true) scmClient, err := getScmClientWithTransport(provider)
if err != nil { if err != nil {
return nil, err return nil, usererror.BadRequestf("could not create client: %s", err)
} }
if spaceSlug == "" { if spaceSlug == "" {
return nil, usererror.BadRequest("provider space identifier is missing") return nil, usererror.BadRequest("provider space identifier is missing")
} }
const pageSize = 100
opts := scm.RepoListOptions{
ListOptions: scm.ListOptions{
Page: 0,
Size: pageSize,
},
RepoSearchTerm: scm.RepoSearchTerm{
User: spaceSlug,
},
}
repos := make([]RepositoryInfo, 0) repos := make([]RepositoryInfo, 0)
for { opts := scm.ListOptions{Size: 100}
opts.Page++
scmRepos, scmResp, err := scmClient.Repositories.ListV2(ctx, opts) for {
scmRepos, scmResp, err := scmClient.Repositories.List(ctx, opts)
if err = convertSCMError(provider, spaceSlug, scmResp, err); err != nil { if err = convertSCMError(provider, spaceSlug, scmResp, err); err != nil {
return nil, err return nil, err
} }
@ -249,6 +251,13 @@ func LoadRepositoriesFromProviderSpace(
DefaultBranch: scmRepo.Branch, DefaultBranch: scmRepo.Branch,
}) })
} }
opts.Page = scmResp.Page.Next
opts.URL = scmResp.Page.NextURL
if opts.Page == 0 && opts.URL == "" {
break
}
} }
return repos, nil return repos, nil