Skip to content

Commit

Permalink
Cr 14126 - support bitbucket cloud (#368)
Browse files Browse the repository at this point in the history
  • Loading branch information
kim-codefresh authored Aug 23, 2022
1 parent 06597cf commit c107fd3
Show file tree
Hide file tree
Showing 8 changed files with 606 additions and 2 deletions.
2 changes: 1 addition & 1 deletion docs/commands/argocd-autopilot_repo_bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ argocd-autopilot repo bootstrap [flags]
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
-n, --namespace string If present, the namespace scope for this CLI request
--namespace-labels stringToString Optional labels that will be set on the namespace resource. (e.g. "key1=value1,key2=value2" (default [])
--provider string The git provider, one of: azure|bitbucket-server|gitea|github|gitlab
--provider string The git provider, one of: azure|bitbucket|bitbucket-server|gitea|github|gitlab
--recover Installs Argo-CD on a cluster without pushing installation manifests to the git repository. This is meant to be used together with --app flag to use the same Argo-CD manifests that exists in the git repository (e.g. --app https://github.com/git-user/repo-name/bootstrap/argo-cd)
--repo string Repository URL [GIT_REPO]
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/go-git/go-git/v5 v5.4.2
github.com/golang/mock v1.6.0
github.com/google/go-github/v43 v43.0.0
github.com/ktrysmt/go-bitbucket v0.9.49
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
Expand Down Expand Up @@ -789,6 +790,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/ktrysmt/go-bitbucket v0.9.40/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno=
github.com/ktrysmt/go-bitbucket v0.9.49 h1:VVfdYIw1SLmgD4xremGkyVY8oI84m9hSbZTK3FyBjxA=
github.com/ktrysmt/go-bitbucket v0.9.49/go.mod h1:aB/IUpoFE65X84soIfgUPT53bzp/jfYoffLN2mg3bFc=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/libopenstorage/openstorage v1.0.0/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
Expand Down
118 changes: 118 additions & 0 deletions pkg/git/bitbucket/mocks/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/git/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var (
}

supportedProviders = map[string]func(*ProviderOptions) (Provider, error){
"bitbucket": newBitbucket,
BitbucketServer: newBitbucketServer,
"github": newGithub,
"gitea": newGitea,
Expand Down
171 changes: 171 additions & 0 deletions pkg/git/provider_bitbucket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package git

import (
"context"
"errors"
"fmt"

bb "github.com/ktrysmt/go-bitbucket"
)

//go:generate mockgen -destination=./bitbucket/mocks/client.go -package=mocks -source=./provider_bitbucket.go bbRepo bbUser

type (
bitbucket struct {
opts *ProviderOptions
Repository bbRepo
User bbUser
}

bbRepo interface {
Create(ro *bb.RepositoryOptions) (*bb.Repository, error)
Get(ro *bb.RepositoryOptions) (*bb.Repository, error)
}

bbUser interface {
Profile() (*bb.User, error)
Emails() (interface{}, error)
}
)

func newBitbucket(opts *ProviderOptions) (Provider, error) {
c := bb.NewBasicAuth(opts.Auth.Username, opts.Auth.Password)
if c == nil {
return nil, errors.New("Authentication info is invalid")
}
g := &bitbucket{
opts: opts,
Repository: c.Repositories.Repository,
User: c.User,
}

return g, nil

}

func (g *bitbucket) CreateRepository(ctx context.Context, orgRepo string) (string, error) {
opts, err := getDefaultRepoOptions(orgRepo)
if err != nil {
return "", err
}

createOpts := &bb.RepositoryOptions{
Owner: opts.Owner,
RepoSlug: opts.Name,
Scm: "git",
}

if opts.Private {
createOpts.IsPrivate = fmt.Sprintf("%t", opts.Private)
}

p, err := g.Repository.Create(createOpts)

if err != nil {
return "", fmt.Errorf("failed creating the repository \"%s\" under \"%s\": %w", opts.Name, opts.Owner, err)
}

var cloneUrl string
cloneLinksObj := p.Links["clone"]
for _, cloneLink := range cloneLinksObj.([]interface{}) {
link := cloneLink.(map[string]interface{})
if link["name"].(string) == "https" {
cloneUrl = link["href"].(string)
}
}

if cloneUrl == "" {
return "", fmt.Errorf("clone url is empty")
}

return cloneUrl, err
}

func (g *bitbucket) GetDefaultBranch(ctx context.Context, orgRepo string) (string, error) {
opts, err := getDefaultRepoOptions(orgRepo)
if err != nil {
return "", err
}

repoOpts := &bb.RepositoryOptions{
Owner: opts.Owner,
RepoSlug: opts.Name,
Scm: "git",
}

if opts.Private {
repoOpts.IsPrivate = fmt.Sprintf("%t", opts.Private)
}

repo, err := g.Repository.Get(repoOpts)
if err != nil {
return "", err
}

return repo.Mainbranch.Name, nil

}

func (g *bitbucket) GetAuthor(_ context.Context) (username, email string, err error) {
authUser, err := g.getAuthenticatedUser()
if err != nil {
return
}

username = authUser.Username

authUserEmail, err := g.getAuthenticatedUserEmail()
if err != nil || authUserEmail == "" {
email = authUser.Username
return
}

email = authUserEmail

return
}

func (g *bitbucket) getAuthenticatedUser() (*bb.User, error) {
user, err := g.User.Profile()

if err != nil {
return nil, err
}

return user, nil
}

func (g *bitbucket) getAuthenticatedUserEmail() (string, error) {
emails, err := g.User.Emails()
if err != nil {
return "", err
}

userEmails := emails.(map[string]interface{})
var lastEmailInfo map[string]interface{}

for _, emailValues := range userEmails["values"].([]interface{}) {
emailInfo := emailValues.(map[string]interface{})
isPrimary := emailInfo["is_primary"].(bool)
isConfirmed := emailInfo["is_confirmed"].(bool)
isLastPrimary, lastExist := lastEmailInfo["is_primary"].(bool)
if isConfirmed && isPrimary {
lastEmailInfo = emailInfo
break
}

if isPrimary {
lastEmailInfo = emailInfo
}

if ((lastExist && !isLastPrimary) || !lastExist) && isConfirmed {
lastEmailInfo = emailInfo
}
}

if email, ok := lastEmailInfo["email"].(string); ok {
return email, nil
}

return "", nil
}
Loading

0 comments on commit c107fd3

Please sign in to comment.