Skip to content

Commit

Permalink
Support gitlab as a SCM provider (#209)
Browse files Browse the repository at this point in the history
* Added gitlab support

* Generated mocks for gitlab client

* Added tests for gitlab provider

* Added gitlab to be a part of the supported providers

* Fixed typo

* ran codegen

* fixed failed test
  • Loading branch information
danielm-codefresh authored Nov 28, 2021
1 parent b769e2e commit 03750ab
Show file tree
Hide file tree
Showing 9 changed files with 429 additions and 3 deletions.
2 changes: 1 addition & 1 deletion docs/Getting-Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export GIT_REPO=https://github.com/owner/name?ref=gitops_branch

#### Using a Specific git Provider
You can add the `--provider` flag to the `repo bootstrap` command, to enforce using a specific provider when creating a new repository. If the value is not supplied, the code will attempt to infer it from the clone URL.
Autopilot currently support github and gitea as SCM providers.
Autopilot currently support github, gitlab and gitea as SCM providers.

All the following commands will use the variables you supplied in order to manage your GitOps repository.

Expand Down
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 @@ -45,7 +45,7 @@ argocd-autopilot repo bootstrap [flags]
--installation-mode string One of: normal|flat. If flat, will commit the bootstrap manifests, otherwise will commit the bootstrap kustomization.yaml (default "normal")
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
-n, --namespace string If present, the namespace scope for this CLI request
--provider string The git provider, one of: gitea|github
--provider string The git provider, one of: gitea|github|gitlab
--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 @@ -18,6 +18,7 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.7.0
github.com/xanzy/go-gitlab v0.52.2
k8s.io/api v0.21.3
k8s.io/apimachinery v0.21.1
k8s.io/cli-runtime v0.21.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,8 @@ github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgq
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/xanzy/go-gitlab v0.50.0/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE=
github.com/xanzy/go-gitlab v0.52.2 h1:gkgg1z4ON70sphibtD86Bfmt1qV3mZ0pU0CBBCFAEvQ=
github.com/xanzy/go-gitlab v0.52.2/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
Expand Down
129 changes: 129 additions & 0 deletions pkg/git/gitlab/mocks/gitlab_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 @@ -53,6 +53,7 @@ var (
var supportedProviders = map[string]func(*ProviderOptions) (Provider, error){
"github": newGithub,
"gitea": newGitea,
"gitlab": newGitlab,
}

// New creates a new git provider
Expand Down
102 changes: 102 additions & 0 deletions pkg/git/provider_gitlab.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package git

import (
"context"
"fmt"

gl "github.com/xanzy/go-gitlab"
)

//go:generate mockery --name GitlabClient --output gitlab/mocks --case snake

type (
GitlabClient interface {
CurrentUser(options ...gl.RequestOptionFunc) (*gl.User, *gl.Response, error)
CreateProject(opt *gl.CreateProjectOptions, options ...gl.RequestOptionFunc) (*gl.Project, *gl.Response, error)
ListGroups(opt *gl.ListGroupsOptions, options ...gl.RequestOptionFunc) ([]*gl.Group, *gl.Response, error)
}

clientImpl struct {
gl.ProjectsService
gl.UsersService
gl.GroupsService
}

gitlab struct {
opts *ProviderOptions
client GitlabClient
}
)

func newGitlab(opts *ProviderOptions) (Provider, error) {
c, err := gl.NewClient(opts.Auth.Password)
if err != nil {
return nil, err
}

g := &gitlab{
opts: opts,
client: &clientImpl{
ProjectsService: *c.Projects,
UsersService: *c.Users,
GroupsService: *c.Groups,
},
}

return g, nil
}

func (g *gitlab) CreateRepository(ctx context.Context, opts *CreateRepoOptions) (string, error) {
authUser, res, err := g.client.CurrentUser()
if err != nil {
if res.StatusCode == 401 {
return "", ErrAuthenticationFailed(err)
}

return "", err
}

createOpts := gl.CreateProjectOptions{
Name: &opts.Name,
Visibility: gl.Visibility(gl.PublicVisibility),
}

if opts.Private {
createOpts.Visibility = gl.Visibility(gl.PrivateVisibility)
}

if authUser.Username != opts.Owner {
groupId, err := g.getGroupIdByName(opts.Owner)
if err != nil {
return "", err
}
createOpts.NamespaceID = gl.Int(groupId)
}

p, _, err := g.client.CreateProject(&createOpts)
if err != nil {
return "", fmt.Errorf("failed creating the project %s under %s: %w", opts.Name, opts.Owner, err)
}

if p.WebURL == "" {
return "", fmt.Errorf("project url is empty")
}

return p.WebURL, err
}

func (g *gitlab) getGroupIdByName(groupName string) (int, error) {
groups, _, err := g.client.ListGroups(&gl.ListGroupsOptions{
MinAccessLevel: gl.AccessLevel(gl.DeveloperPermissions),
})
if err != nil {
return 0, err
}

for _, group := range groups {
if group.Path == groupName {
return group.ID, nil
}
}
return 0, fmt.Errorf("group %s not found", groupName)
}
Loading

0 comments on commit 03750ab

Please sign in to comment.