@@ -5,26 +5,142 @@ import (
55 "fmt"
66
77 "github.com/fluxcd/go-git-providers/github"
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+ "sigs.k8s.io/controller-runtime/pkg/log"
13+
14+ mpasv1alpha1 "github.com/open-component-model/git-controller/apis/mpas/v1alpha1"
815 "github.com/open-component-model/git-controller/pkg/providers"
916)
1017
18+ const (
19+ tokenKey = "token"
20+ providerType = "github"
21+ defaultDomain = "github.com"
22+ )
23+
24+ // Client github.
1125type Client struct {
12- // TODO: Figure out how to get this.
13- BaseURL string
26+ client client.Client
27+ next providers.Provider
28+ }
29+
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
1435}
1536
16- func NewClient () * Client {
17- return & Client {}
37+ // NewClient creates a new GitHub client.
38+ func NewClient (client client.Client , next providers.Provider ) * Client {
39+ return & Client {
40+ client : client ,
41+ next : next ,
42+ }
1843}
1944
2045var _ providers.Provider = & Client {}
2146
22- func (c * Client ) CreateRepository (ctx context.Context , owner , repo string ) error {
23- _ , err := github .NewClient ()
47+ func (c * Client ) CreateRepository (ctx context.Context , obj mpasv1alpha1.Repository ) error {
48+ if obj .Spec .Provider != providerType {
49+ if c .next == nil {
50+ return fmt .Errorf ("can't handle provider type '%s' and no next provider is configured" , obj .Spec .Provider )
51+ }
52+
53+ return c .next .CreateRepository (ctx , obj )
54+ }
55+
56+ authenticationOption , err := c .constructAuthenticationOption (ctx , obj )
57+ if err != nil {
58+ return err
59+ }
60+
61+ gc , err := github .NewClient (authenticationOption )
2462 if err != nil {
2563 return fmt .Errorf ("failed to create github client: %w" , err )
2664 }
2765
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+
72+ domain := defaultDomain
73+ if obj .Spec .Domain != "" {
74+ domain = obj .Spec .Domain
75+ }
76+
77+ if obj .Spec .IsOrganization {
78+ return c .createOrganizationRepository (ctx , gc , domain , visibility , obj .Spec )
79+ }
80+
81+ return c .createUserRepository (ctx , gc , domain , visibility , obj .Spec )
82+ }
83+
84+ // constructAuthenticationOption will take the object and construct an authentication option.
85+ // For now, only token secret is supported, this will be extended in the future.
86+ func (c * Client ) constructAuthenticationOption (ctx context.Context , obj mpasv1alpha1.Repository ) (gitprovider.ClientOption , error ) {
87+ secret := & v1.Secret {}
88+ if err := c .client .Get (ctx , types.NamespacedName {
89+ Name : obj .Spec .Credentials .SecretRef .Name ,
90+ Namespace : obj .Namespace ,
91+ }, secret ); err != nil {
92+ return nil , fmt .Errorf ("failed to get secret: %w" , err )
93+ }
94+
95+ token , ok := secret .Data [tokenKey ]
96+ if ! ok {
97+ return nil , fmt .Errorf ("token '%s' not found in secret" , tokenKey )
98+ }
99+
100+ return gitprovider .WithOAuth2Token (string (token )), nil
101+ }
102+
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+ repo , err := gc .OrgRepositories ().Create (ctx , gitprovider.OrgRepositoryRef {
107+ OrganizationRef : gitprovider.OrganizationRef {
108+ Domain : domain ,
109+ Organization : spec .Owner ,
110+ },
111+ RepositoryName : spec .RepositoryName ,
112+ }, gitprovider.RepositoryInfo {
113+ DefaultBranch : gitprovider .StringVar ("main" ),
114+ Visibility : & visibility ,
115+ })
116+ if err != nil {
117+ return fmt .Errorf ("failed to create repository: %w" , err )
118+ }
119+
120+ logger .Info ("organization repository successfully created" , "name" , repo .Repository ().String ())
121+
122+ return nil
123+ }
124+
125+ func (c * Client ) createUserRepository (ctx context.Context , gc gitprovider.Client , domain string , visibility gitprovider.RepositoryVisibility , spec mpasv1alpha1.RepositorySpec ) error {
126+ logger := log .FromContext (ctx )
127+
128+ repo , err := gc .UserRepositories ().Create (ctx , gitprovider.UserRepositoryRef {
129+ UserRef : gitprovider.UserRef {
130+ Domain : domain ,
131+ UserLogin : spec .Owner ,
132+ },
133+ RepositoryName : spec .RepositoryName ,
134+ }, gitprovider.RepositoryInfo {
135+ DefaultBranch : gitprovider .StringVar ("main" ),
136+ Visibility : & visibility ,
137+ })
138+ if err != nil {
139+ return fmt .Errorf ("failed to create repository: %w" , err )
140+ }
141+
142+ logger .Info ("user repository successfully created" , "name" , repo .Repository ().String ())
143+
28144 return nil
29145}
30146
0 commit comments