Skip to content
This repository was archived by the owner on May 9, 2025. It is now read-only.

Commit d96b3a0

Browse files
committed
feat: adding gitlab support
1 parent 1a2e13a commit d96b3a0

File tree

7 files changed

+216
-104
lines changed

7 files changed

+216
-104
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ require (
9191
github.com/google/uuid v1.3.0 // indirect
9292
github.com/gorilla/mux v1.8.0 // indirect
9393
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
94+
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
95+
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
9496
github.com/imdario/mergo v0.3.13 // indirect
9597
github.com/inconshreveable/mousetrap v1.1.0 // indirect
9698
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
@@ -139,6 +141,7 @@ require (
139141
github.com/tonglil/buflogr v1.0.1 // indirect
140142
github.com/ulikunitz/xz v0.5.11 // indirect
141143
github.com/vbatts/tar-split v0.11.2 // indirect
144+
github.com/xanzy/go-gitlab v0.81.0 // indirect
142145
github.com/xanzy/ssh-agent v0.3.3 // indirect
143146
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
144147
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect

go.sum

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
468468
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
469469
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
470470
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
471+
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
471472
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
472473
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
473474
github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=
@@ -699,11 +700,17 @@ github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FK
699700
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
700701
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
701702
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
703+
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
704+
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
705+
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
706+
github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
702707
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
703708
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
704709
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
705710
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
706711
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
712+
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
713+
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
707714
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
708715
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
709716
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
@@ -825,8 +832,10 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef
825832
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
826833
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
827834
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
835+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
828836
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
829837
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
838+
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
830839
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
831840
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
832841
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
@@ -1160,6 +1169,8 @@ github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1
11601169
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
11611170
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
11621171
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
1172+
github.com/xanzy/go-gitlab v0.81.0 h1:ofbhZ5ZY9AjHATWQie4qd2JfncdUmvcSA/zfQB767Dk=
1173+
github.com/xanzy/go-gitlab v0.81.0/go.mod h1:VMbY3JIWdZ/ckvHbQqkyd3iYk2aViKrNIQ23IbFMQDo=
11631174
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
11641175
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
11651176
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=

main.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/open-component-model/git-controller/pkg/gogit"
1212
"github.com/open-component-model/git-controller/pkg/providers/github"
13+
"github.com/open-component-model/git-controller/pkg/providers/gitlab"
1314
"k8s.io/apimachinery/pkg/runtime"
1415
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
1516
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
@@ -101,7 +102,8 @@ func main() {
101102
os.Exit(1)
102103
}
103104

104-
githubProvider := github.NewClient(mgr.GetClient(), nil)
105+
gitlabProvider := gitlab.NewClient(mgr.GetClient(), nil)
106+
githubProvider := github.NewClient(mgr.GetClient(), gitlabProvider)
105107
if err = (&mpascontrollers.RepositoryReconciler{
106108
Client: mgr.GetClient(),
107109
Scheme: mgr.GetScheme(),

pkg/providers/github/github.go

Lines changed: 9 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ import (
99
v1 "k8s.io/api/core/v1"
1010
"k8s.io/apimachinery/pkg/types"
1111
"sigs.k8s.io/controller-runtime/pkg/client"
12-
"sigs.k8s.io/controller-runtime/pkg/log"
1312

1413
mpasv1alpha1 "github.com/open-component-model/git-controller/apis/mpas/v1alpha1"
1514
"github.com/open-component-model/git-controller/pkg/providers"
15+
"github.com/open-component-model/git-controller/pkg/providers/gogit"
1616
)
1717

1818
const (
1919
tokenKey = "token"
2020
providerType = "github"
21-
defaultDomain = "github.com"
21+
defaultDomain = github.DefaultDomain
2222
)
2323

2424
// Client github.
@@ -27,13 +27,6 @@ type Client struct {
2727
next providers.Provider
2828
}
2929

30-
// TODO: Use this instead and somehow abstract the two clients.
31-
type RepositoryOpts struct {
32-
Owner string
33-
Domain string
34-
Visibility gitprovider.RepositoryVisibility
35-
}
36-
3730
// NewClient creates a new GitHub client.
3831
func NewClient(client client.Client, next providers.Provider) *Client {
3932
return &Client{
@@ -58,27 +51,21 @@ func (c *Client) CreateRepository(ctx context.Context, obj mpasv1alpha1.Reposito
5851
return err
5952
}
6053

61-
gc, err := github.NewClient(authenticationOption)
62-
if err != nil {
63-
return fmt.Errorf("failed to create github client: %w", err)
64-
}
65-
66-
visibility := gitprovider.RepositoryVisibility(obj.Spec.Visibility)
67-
68-
if err := gitprovider.ValidateRepositoryVisibility(visibility); err != nil {
69-
return fmt.Errorf("failed to validate visibility: %w", err)
70-
}
71-
7254
domain := defaultDomain
7355
if obj.Spec.Domain != "" {
7456
domain = obj.Spec.Domain
7557
}
7658

59+
gc, err := github.NewClient(authenticationOption, gitprovider.WithDomain(domain))
60+
if err != nil {
61+
return fmt.Errorf("failed to create github client: %w", err)
62+
}
63+
7764
if obj.Spec.IsOrganization {
78-
return c.createOrganizationRepository(ctx, gc, domain, visibility, obj.Spec)
65+
return gogit.CreateOrganizationRepository(ctx, gc, domain, obj.Spec)
7966
}
8067

81-
return c.createUserRepository(ctx, gc, domain, visibility, obj.Spec)
68+
return gogit.CreateUserRepository(ctx, gc, domain, obj.Spec)
8269
}
8370

8471
// constructAuthenticationOption will take the object and construct an authentication option.
@@ -100,86 +87,6 @@ func (c *Client) constructAuthenticationOption(ctx context.Context, obj mpasv1al
10087
return gitprovider.WithOAuth2Token(string(token)), nil
10188
}
10289

103-
func (c *Client) createOrganizationRepository(ctx context.Context, gc gitprovider.Client, domain string, visibility gitprovider.RepositoryVisibility, spec mpasv1alpha1.RepositorySpec) error {
104-
logger := log.FromContext(ctx)
105-
106-
ref := gitprovider.OrgRepositoryRef{
107-
OrganizationRef: gitprovider.OrganizationRef{
108-
Domain: domain,
109-
Organization: spec.Owner,
110-
},
111-
RepositoryName: spec.RepositoryName,
112-
}
113-
info := gitprovider.RepositoryInfo{
114-
DefaultBranch: gitprovider.StringVar("main"),
115-
Visibility: &visibility,
116-
}
117-
118-
switch spec.ExistingRepositoryPolicy {
119-
case mpasv1alpha1.ExistingRepositoryPolicyFail:
120-
if _, err := gc.OrgRepositories().Create(ctx, ref, info); err != nil {
121-
return fmt.Errorf("failed to create repository: %w", err)
122-
}
123-
124-
logger.Info("successfully created organization repository", "domain", domain, "repository", spec.RepositoryName)
125-
case mpasv1alpha1.ExistingRepositoryPolicyAdopt:
126-
_, created, err := gc.OrgRepositories().Reconcile(ctx, ref, info)
127-
if err != nil {
128-
return fmt.Errorf("failed to reconcile repository: %w", err)
129-
}
130-
131-
if !created {
132-
logger.Info("using existing repository", "domain", domain, "repository", spec.RepositoryName)
133-
} else {
134-
logger.Info("successfully created organization repository", "domain", domain, "repository", spec.RepositoryName)
135-
}
136-
default:
137-
return fmt.Errorf("unknown repository policy '%s'", spec.ExistingRepositoryPolicy)
138-
}
139-
140-
return nil
141-
}
142-
143-
func (c *Client) createUserRepository(ctx context.Context, gc gitprovider.Client, domain string, visibility gitprovider.RepositoryVisibility, spec mpasv1alpha1.RepositorySpec) error {
144-
logger := log.FromContext(ctx)
145-
146-
ref := gitprovider.UserRepositoryRef{
147-
UserRef: gitprovider.UserRef{
148-
Domain: domain,
149-
UserLogin: spec.Owner,
150-
},
151-
RepositoryName: spec.RepositoryName,
152-
}
153-
info := gitprovider.RepositoryInfo{
154-
DefaultBranch: gitprovider.StringVar("main"),
155-
Visibility: &visibility,
156-
}
157-
158-
switch spec.ExistingRepositoryPolicy {
159-
case mpasv1alpha1.ExistingRepositoryPolicyFail:
160-
if _, err := gc.UserRepositories().Create(ctx, ref, info); err != nil {
161-
return fmt.Errorf("failed to create repository: %w", err)
162-
}
163-
164-
logger.Info("successfully created user repository", "domain", domain, "repository", spec.RepositoryName)
165-
case mpasv1alpha1.ExistingRepositoryPolicyAdopt:
166-
_, created, err := gc.UserRepositories().Reconcile(ctx, ref, info)
167-
if err != nil {
168-
return fmt.Errorf("failed to reconcile repository: %w", err)
169-
}
170-
171-
if !created {
172-
logger.Info("using existing repository", "domain", domain, "repository", spec.RepositoryName)
173-
} else {
174-
logger.Info("successfully created user repository", "domain", domain, "repository", spec.RepositoryName)
175-
}
176-
default:
177-
return fmt.Errorf("unknown repository policy '%s'", spec.ExistingRepositoryPolicy)
178-
}
179-
180-
return nil
181-
}
182-
18390
func (c *Client) CreatePullRequest(ctx context.Context, owner, repo, title, branch, description string) error {
18491
return nil
18592
}

pkg/providers/gitlab/gitlab.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,86 @@
11
package gitlab
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/fluxcd/go-git-providers/gitlab"
8+
"github.com/fluxcd/go-git-providers/gitprovider"
9+
v1 "k8s.io/api/core/v1"
10+
"k8s.io/apimachinery/pkg/types"
11+
"sigs.k8s.io/controller-runtime/pkg/client"
12+
13+
mpasv1alpha1 "github.com/open-component-model/git-controller/apis/mpas/v1alpha1"
14+
"github.com/open-component-model/git-controller/pkg/providers"
15+
"github.com/open-component-model/git-controller/pkg/providers/gogit"
16+
)
17+
18+
const (
19+
tokenKey = "token"
20+
providerType = "gitlab"
21+
defaultDomain = gitlab.DefaultDomain
22+
)
23+
24+
var (
25+
// for now, only personal tokens are supported
26+
tokenType = "personal"
27+
)
28+
29+
// Client gitlab.
30+
type Client struct {
31+
client client.Client
32+
next providers.Provider
33+
}
34+
35+
// NewClient creates a new Gitlab client.
36+
func NewClient(client client.Client, next providers.Provider) *Client {
37+
return &Client{
38+
client: client,
39+
next: next,
40+
}
41+
}
42+
43+
var _ providers.Provider = &Client{}
44+
45+
func (c *Client) CreateRepository(ctx context.Context, obj mpasv1alpha1.Repository) error {
46+
if obj.Spec.Provider != providerType {
47+
if c.next == nil {
48+
return fmt.Errorf("can't handle provider type '%s' and no next provider is configured", obj.Spec.Provider)
49+
}
50+
51+
return c.next.CreateRepository(ctx, obj)
52+
}
53+
54+
secret := &v1.Secret{}
55+
if err := c.client.Get(ctx, types.NamespacedName{
56+
Name: obj.Spec.Credentials.SecretRef.Name,
57+
Namespace: obj.Namespace,
58+
}, secret); err != nil {
59+
return fmt.Errorf("failed to get secret: %w", err)
60+
}
61+
62+
token, ok := secret.Data[tokenKey]
63+
if !ok {
64+
return fmt.Errorf("token '%s' not found in secret", tokenKey)
65+
}
66+
67+
domain := defaultDomain
68+
if obj.Spec.Domain != "" {
69+
domain = obj.Spec.Domain
70+
}
71+
72+
gc, err := gitlab.NewClient(string(token), tokenType, gitprovider.WithDomain(domain))
73+
if err != nil {
74+
return fmt.Errorf("failed to create github client: %w", err)
75+
}
76+
77+
if obj.Spec.IsOrganization {
78+
return gogit.CreateOrganizationRepository(ctx, gc, domain, obj.Spec)
79+
}
80+
81+
return gogit.CreateUserRepository(ctx, gc, domain, obj.Spec)
82+
}
83+
84+
func (c *Client) CreatePullRequest(ctx context.Context, owner, repo, title, branch, description string) error {
85+
return nil
86+
}

0 commit comments

Comments
 (0)