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

Commit b1c3f0d

Browse files
authored
feat: adding CODEOWNERS file using maintainers (#22)
* feat: adding CODEOWNERS file using maintainers * delete the repository if codeowners file failed to be added
1 parent 3b51263 commit b1c3f0d

File tree

2 files changed

+115
-4
lines changed

2 files changed

+115
-4
lines changed

pkg/providers/gitea/gitea.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
package gitea
66

77
import (
8+
"bytes"
89
"context"
10+
"encoding/base64"
11+
"errors"
912
"fmt"
1013

1114
"code.gitea.io/sdk/gitea"
@@ -88,6 +91,33 @@ func (c *Client) CreateRepository(ctx context.Context, obj mpasv1alpha1.Reposito
8891
return fmt.Errorf("failed to create repositroy: %w", err)
8992
}
9093

94+
if len(obj.Spec.Maintainers) != 0 {
95+
var content []byte
96+
buffer := bytes.NewBuffer(content)
97+
98+
for _, m := range obj.Spec.Maintainers {
99+
buffer.WriteString(m)
100+
}
101+
102+
encoded := base64.StdEncoding.EncodeToString(buffer.Bytes())
103+
104+
_, _, err := client.CreateFile(obj.Spec.Owner, obj.Spec.RepositoryName, "CODEOWNERS", gitea.CreateFileOptions{
105+
FileOptions: gitea.FileOptions{
106+
Message: "Adding CODEOWNERS file.",
107+
BranchName: "main",
108+
},
109+
Content: encoded,
110+
})
111+
112+
if err != nil {
113+
if _, derr := client.DeleteRepo(obj.Spec.Owner, obj.Spec.RepositoryName); derr != nil {
114+
err = errors.Join(err, derr)
115+
}
116+
117+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
118+
}
119+
}
120+
91121
return nil
92122
}
93123

pkg/providers/gogit/gogit.go

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ package gogit
66

77
import (
88
"context"
9+
"errors"
910
"fmt"
11+
"strings"
1012

1113
"github.com/fluxcd/go-git-providers/gitprovider"
1214
deliveryv1alpha1 "github.com/open-component-model/git-controller/apis/delivery/v1alpha1"
@@ -37,22 +39,44 @@ func CreateOrganizationRepository(ctx context.Context, gc gitprovider.Client, do
3739
Visibility: &visibility,
3840
}
3941

42+
createOpts, err := gitprovider.MakeRepositoryCreateOptions(&gitprovider.RepositoryCreateOptions{AutoInit: gitprovider.BoolVar(true)})
43+
if err != nil {
44+
return fmt.Errorf("failed to create _create_ options for repository: %w", err)
45+
}
46+
4047
switch spec.ExistingRepositoryPolicy {
4148
case mpasv1alpha1.ExistingRepositoryPolicyFail:
42-
if _, err := gc.OrgRepositories().Create(ctx, ref, info); err != nil {
49+
repo, err := gc.OrgRepositories().Create(ctx, ref, info, &createOpts)
50+
if err != nil {
4351
return fmt.Errorf("failed to create repository: %w", err)
4452
}
4553

54+
if err := createCodeownersFile(ctx, repo, spec.Maintainers); err != nil {
55+
if cerr := repo.Delete(ctx); cerr != nil {
56+
err = errors.Join(err, cerr)
57+
}
58+
59+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
60+
}
61+
4662
logger.Info("successfully created organization repository", "domain", domain, "repository", spec.RepositoryName)
4763
case mpasv1alpha1.ExistingRepositoryPolicyAdopt:
48-
_, created, err := gc.OrgRepositories().Reconcile(ctx, ref, info)
64+
repo, created, err := gc.OrgRepositories().Reconcile(ctx, ref, info, &createOpts)
4965
if err != nil {
5066
return fmt.Errorf("failed to reconcile repository: %w", err)
5167
}
5268

5369
if !created {
5470
logger.Info("using existing repository", "domain", domain, "repository", spec.RepositoryName)
5571
} else {
72+
if err := createCodeownersFile(ctx, repo, spec.Maintainers); err != nil {
73+
if cerr := repo.Delete(ctx); cerr != nil {
74+
err = errors.Join(err, cerr)
75+
}
76+
77+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
78+
}
79+
5680
logger.Info("successfully created organization repository", "domain", domain, "repository", spec.RepositoryName)
5781
}
5882
default:
@@ -84,22 +108,44 @@ func CreateUserRepository(ctx context.Context, gc gitprovider.Client, domain str
84108
Visibility: &visibility,
85109
}
86110

111+
createOpts, err := gitprovider.MakeRepositoryCreateOptions(&gitprovider.RepositoryCreateOptions{AutoInit: gitprovider.BoolVar(true)})
112+
if err != nil {
113+
return fmt.Errorf("failed to create _create_ options for repository: %w", err)
114+
}
115+
87116
switch spec.ExistingRepositoryPolicy {
88117
case mpasv1alpha1.ExistingRepositoryPolicyFail:
89-
if _, err := gc.UserRepositories().Create(ctx, ref, info); err != nil {
118+
repo, err := gc.UserRepositories().Create(ctx, ref, info, &createOpts)
119+
if err != nil {
90120
return fmt.Errorf("failed to create repository: %w", err)
91121
}
92122

123+
if err := createCodeownersFile(ctx, repo, spec.Maintainers); err != nil {
124+
if cerr := repo.Delete(ctx); cerr != nil {
125+
err = errors.Join(err, cerr)
126+
}
127+
128+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
129+
}
130+
93131
logger.Info("successfully created user repository", "domain", domain, "repository", spec.RepositoryName)
94132
case mpasv1alpha1.ExistingRepositoryPolicyAdopt:
95-
_, created, err := gc.UserRepositories().Reconcile(ctx, ref, info)
133+
repo, created, err := gc.UserRepositories().Reconcile(ctx, ref, info, &createOpts)
96134
if err != nil {
97135
return fmt.Errorf("failed to reconcile repository: %w", err)
98136
}
99137

100138
if !created {
101139
logger.Info("using existing repository", "domain", domain, "repository", spec.RepositoryName)
102140
} else {
141+
if err := createCodeownersFile(ctx, repo, spec.Maintainers); err != nil {
142+
if cerr := repo.Delete(ctx); cerr != nil {
143+
err = errors.Join(err, cerr)
144+
}
145+
146+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
147+
}
148+
103149
logger.Info("successfully created user repository", "domain", domain, "repository", spec.RepositoryName)
104150
}
105151
default:
@@ -194,3 +240,38 @@ func CreateUserPullRequest(ctx context.Context, gc gitprovider.Client, domain, b
194240

195241
return nil
196242
}
243+
244+
// Repositories groups together a common functionality of both repository types.
245+
type Repositories interface {
246+
Commits() gitprovider.CommitClient
247+
}
248+
249+
func createCodeownersFile(ctx context.Context, repo Repositories, maintainers []string) error {
250+
if len(maintainers) == 0 {
251+
return nil
252+
}
253+
254+
logger := log.FromContext(ctx)
255+
256+
content := strings.Builder{}
257+
258+
for _, m := range maintainers {
259+
_, _ = content.WriteString(fmt.Sprintf("%s\n", m))
260+
}
261+
262+
files := []gitprovider.CommitFile{
263+
{
264+
Path: gitprovider.StringVar("CODEOWNERS"),
265+
Content: gitprovider.StringVar(content.String()),
266+
},
267+
}
268+
269+
commit, err := repo.Commits().Create(ctx, "main", "adding CODEOWNERS", files)
270+
if err != nil {
271+
return fmt.Errorf("failed to create CODEOWNERS file: %w", err)
272+
}
273+
274+
logger.Info("successfully added CODEOWNERS", "url", commit.Get().URL)
275+
276+
return nil
277+
}

0 commit comments

Comments
 (0)