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

Commit 1df3231

Browse files
committed
feat: adding CODEOWNERS file using maintainers
1 parent 3b51263 commit 1df3231

File tree

5 files changed

+164
-13
lines changed

5 files changed

+164
-13
lines changed

apis/mpas/v1alpha1/repository_types.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ var (
2828
ExistingRepositoryPolicyFail ExistingRepositoryPolicy = "fail"
2929
)
3030

31+
// CommitTemplate defines information that is needed to create the CODEOWNERS file.
32+
type CommitTemplate struct {
33+
Email string `json:"email"`
34+
Name string `json:"name"`
35+
36+
//+optional
37+
Message string `json:"message,omitempty"`
38+
}
39+
40+
// Maintainers defines information needed
41+
type Maintainers struct {
42+
Users []string `json:"users"`
43+
CommitTemplate CommitTemplate `json:"commitTemplate"`
44+
}
45+
3146
// RepositorySpec defines the desired state of Repository
3247
type RepositorySpec struct {
3348
//+required
@@ -49,7 +64,7 @@ type RepositorySpec struct {
4964
//+optional
5065
Domain string `json:"domain,omitempty"`
5166
//+optional
52-
Maintainers []string `json:"maintainers,omitempty"`
67+
Maintainers Maintainers `json:"maintainers,omitempty"`
5368
//+optional
5469
//+kubebuilder:default:=adopt
5570
//+kubebuilder:validation:Enum=adopt;fail

apis/mpas/v1alpha1/zz_generated.deepcopy.go

Lines changed: 37 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/mpas.ocm.software_repositories.yaml

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,30 @@ spec:
6868
default: true
6969
type: boolean
7070
maintainers:
71-
items:
72-
type: string
73-
type: array
71+
description: Maintainers defines information needed
72+
properties:
73+
commitTemplate:
74+
description: CommitTemplate defines information that is needed
75+
to create the CODEOWNERS file.
76+
properties:
77+
email:
78+
type: string
79+
message:
80+
type: string
81+
name:
82+
type: string
83+
required:
84+
- email
85+
- name
86+
type: object
87+
users:
88+
items:
89+
type: string
90+
type: array
91+
required:
92+
- commitTemplate
93+
- users
94+
type: object
7495
owner:
7596
type: string
7697
provider:

pkg/providers/gitea/gitea.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package gitea
77
import (
88
"context"
99
"fmt"
10+
"strings"
1011

1112
"code.gitea.io/sdk/gitea"
1213
v1 "k8s.io/api/core/v1"
@@ -88,6 +89,34 @@ func (c *Client) CreateRepository(ctx context.Context, obj mpasv1alpha1.Reposito
8889
return fmt.Errorf("failed to create repositroy: %w", err)
8990
}
9091

92+
if len(obj.Spec.Maintainers.Users) != 0 {
93+
content := strings.Builder{}
94+
95+
for _, m := range obj.Spec.Maintainers.Users {
96+
_, _ = content.WriteString(fmt.Sprintf("%s\n", m))
97+
}
98+
99+
_, _, err := client.CreateFile(obj.Spec.Owner, obj.Spec.RepositoryName, ".", gitea.CreateFileOptions{
100+
FileOptions: gitea.FileOptions{
101+
Message: obj.Spec.Maintainers.CommitTemplate.Message,
102+
BranchName: "main",
103+
Author: gitea.Identity{
104+
Name: obj.Spec.Maintainers.CommitTemplate.Name,
105+
Email: obj.Spec.Maintainers.CommitTemplate.Email,
106+
},
107+
Committer: gitea.Identity{
108+
Name: obj.Spec.Maintainers.CommitTemplate.Name,
109+
Email: obj.Spec.Maintainers.CommitTemplate.Email,
110+
},
111+
},
112+
Content: content.String(),
113+
})
114+
115+
if err != nil {
116+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
117+
}
118+
}
119+
91120
return nil
92121
}
93122

pkg/providers/gogit/gogit.go

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package gogit
77
import (
88
"context"
99
"fmt"
10+
"strings"
1011

1112
"github.com/fluxcd/go-git-providers/gitprovider"
1213
deliveryv1alpha1 "github.com/open-component-model/git-controller/apis/delivery/v1alpha1"
@@ -39,20 +40,29 @@ func CreateOrganizationRepository(ctx context.Context, gc gitprovider.Client, do
3940

4041
switch spec.ExistingRepositoryPolicy {
4142
case mpasv1alpha1.ExistingRepositoryPolicyFail:
42-
if _, err := gc.OrgRepositories().Create(ctx, ref, info); err != nil {
43+
repo, err := gc.OrgRepositories().Create(ctx, ref, info)
44+
if err != nil {
4345
return fmt.Errorf("failed to create repository: %w", err)
4446
}
4547

48+
if err := createCodeownersFile(ctx, repo, spec.Maintainers); err != nil {
49+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
50+
}
51+
4652
logger.Info("successfully created organization repository", "domain", domain, "repository", spec.RepositoryName)
4753
case mpasv1alpha1.ExistingRepositoryPolicyAdopt:
48-
_, created, err := gc.OrgRepositories().Reconcile(ctx, ref, info)
54+
repo, created, err := gc.OrgRepositories().Reconcile(ctx, ref, info)
4955
if err != nil {
5056
return fmt.Errorf("failed to reconcile repository: %w", err)
5157
}
5258

5359
if !created {
5460
logger.Info("using existing repository", "domain", domain, "repository", spec.RepositoryName)
5561
} else {
62+
if err := createCodeownersFile(ctx, repo, spec.Maintainers); err != nil {
63+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
64+
}
65+
5666
logger.Info("successfully created organization repository", "domain", domain, "repository", spec.RepositoryName)
5767
}
5868
default:
@@ -86,20 +96,29 @@ func CreateUserRepository(ctx context.Context, gc gitprovider.Client, domain str
8696

8797
switch spec.ExistingRepositoryPolicy {
8898
case mpasv1alpha1.ExistingRepositoryPolicyFail:
89-
if _, err := gc.UserRepositories().Create(ctx, ref, info); err != nil {
99+
repo, err := gc.UserRepositories().Create(ctx, ref, info)
100+
if err != nil {
90101
return fmt.Errorf("failed to create repository: %w", err)
91102
}
92103

104+
if err := createCodeownersFile(ctx, repo, spec.Maintainers); err != nil {
105+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
106+
}
107+
93108
logger.Info("successfully created user repository", "domain", domain, "repository", spec.RepositoryName)
94109
case mpasv1alpha1.ExistingRepositoryPolicyAdopt:
95-
_, created, err := gc.UserRepositories().Reconcile(ctx, ref, info)
110+
repo, created, err := gc.UserRepositories().Reconcile(ctx, ref, info)
96111
if err != nil {
97112
return fmt.Errorf("failed to reconcile repository: %w", err)
98113
}
99114

100115
if !created {
101116
logger.Info("using existing repository", "domain", domain, "repository", spec.RepositoryName)
102117
} else {
118+
if err := createCodeownersFile(ctx, repo, spec.Maintainers); err != nil {
119+
return fmt.Errorf("failed to add CODEOWNERS file: %w", err)
120+
}
121+
103122
logger.Info("successfully created user repository", "domain", domain, "repository", spec.RepositoryName)
104123
}
105124
default:
@@ -194,3 +213,38 @@ func CreateUserPullRequest(ctx context.Context, gc gitprovider.Client, domain, b
194213

195214
return nil
196215
}
216+
217+
// Repositories groups together a common functionality of both repository types.
218+
type Repositories interface {
219+
Commits() gitprovider.CommitClient
220+
}
221+
222+
func createCodeownersFile(ctx context.Context, repo Repositories, maintainers mpasv1alpha1.Maintainers) error {
223+
if len(maintainers.Users) == 0 {
224+
return nil
225+
}
226+
227+
logger := log.FromContext(ctx)
228+
229+
content := strings.Builder{}
230+
231+
for _, m := range maintainers.Users {
232+
_, _ = content.WriteString(fmt.Sprintf("%s\n", m))
233+
}
234+
235+
files := []gitprovider.CommitFile{
236+
{
237+
Path: gitprovider.StringVar("."),
238+
Content: gitprovider.StringVar(content.String()),
239+
},
240+
}
241+
242+
commit, err := repo.Commits().Create(ctx, "main", "adding CODEOWNERS", files)
243+
if err != nil {
244+
return fmt.Errorf("failed to create CODEOWNERS file: %w", err)
245+
}
246+
247+
logger.Info("successfully added CODEOWNERS", "url", commit.Get().URL)
248+
249+
return nil
250+
}

0 commit comments

Comments
 (0)