Skip to content

Commit

Permalink
feat(owners): add ability to load complex owners hierarchy
Browse files Browse the repository at this point in the history
Signed-off-by: Massimiliano Giovagnoli <[email protected]>
  • Loading branch information
maxgio92 committed May 4, 2023
1 parent 4e042dc commit c718728
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 88 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ $(foreach bin,$(bins),\

.PHONY: ginkgo
ginkgo:
@$(go) install github.com/onsi/ginkgo/v2/ginkgo
@hash ginkgo || \
$(go) install github.com/onsi/ginkgo/v2/ginkgo

.PHONY: docs
docs:
Expand Down
64 changes: 48 additions & 16 deletions cmd/sync/github/sync_github.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ package github

import (
"fmt"
syncergithub "github.com/maxgio92/peribolos-syncer/internal/github"
"github.com/maxgio92/peribolos-syncer/internal/owners"
"github.com/maxgio92/peribolos-syncer/internal/sync"
"os"
"path"

Expand All @@ -36,7 +33,10 @@ import (
"sigs.k8s.io/yaml"

syncergit "github.com/maxgio92/peribolos-syncer/internal/git"
syncergithub "github.com/maxgio92/peribolos-syncer/internal/github"
"github.com/maxgio92/peribolos-syncer/internal/output"
"github.com/maxgio92/peribolos-syncer/internal/owners"
"github.com/maxgio92/peribolos-syncer/internal/sync"
orgs "github.com/maxgio92/peribolos-syncer/pkg/peribolos"
"github.com/maxgio92/peribolos-syncer/pkg/pgp"
)
Expand All @@ -50,7 +50,8 @@ type options struct {

github syncergithub.GitHubOptions
orgs *orgs.PeribolosOptions
owners *owners.OwnersOptions
owners *owners.OwnersLoadingOptions

git.ListOptions
}

Expand All @@ -60,7 +61,7 @@ func New() *cobra.Command {
CommonOptions: &sync.CommonOptions{},
author: gitobject.Signature{},
github: syncergithub.GitHubOptions{},
owners: &owners.OwnersOptions{},
owners: &owners.OwnersLoadingOptions{},
orgs: &orgs.PeribolosOptions{},
}

Expand Down Expand Up @@ -147,7 +148,7 @@ func (o *options) Run(_ *cobra.Command, _ []string) error {
// Build GitHub client.
githubClient, err := o.github.GitHubClientWithAccessToken(string(token))
if err != nil {
return errors.Wrap(err, "error generating GitHub client with specified access token")
return errors.Wrap(err, "error generating github client with specified access token")
}

// Load Owners hierarchy from specified repository.
Expand All @@ -156,8 +157,8 @@ func (o *options) Run(_ *cobra.Command, _ []string) error {
return err
}

// Get the leaf approvers from the Owners hierarchy.
approvers := maps.Keys(owners.LeafApprovers(o.owners.OwnersPath))
// Load specified people from the Owners structure.
people := o.loadPeopleFromOwners(owners)

// Clone the peribolos config repository.
repo, worktree, local, err := o.github.ForkRepository(
Expand All @@ -179,7 +180,7 @@ func (o *options) Run(_ *cobra.Command, _ []string) error {
}

// Synchronize the Github Team config with Approvers.
if err := orgs.AddTeamMembers(config, o.GitHubOrg, o.GitHubTeam, approvers); err != nil {
if err := orgs.AddTeamMembers(config, o.GitHubOrg, o.GitHubTeam, people); err != nil {
return errors.Wrap(err, "error updating maintainers github team from leaf approvers")
}

Expand All @@ -191,7 +192,7 @@ func (o *options) Run(_ *cobra.Command, _ []string) error {
// Store the change in a commitAll with a log.
commitMsg := fmt.Sprintf(`chore(%s): update %s team members
The update reflects the content of the related repository root's OWNERS.
The update reflects the content of the related repository's OWNERS tree.
%s
Signed-off-by: %s <%s>
Expand Down Expand Up @@ -224,17 +225,17 @@ Signed-off-by: %s <%s>
pr, err := githubClient.CreatePullRequest(
o.GitHubOrg,
o.orgs.ConfigRepo,
fmt.Sprintf("Sync Github Team %s with %s owners", o.GitHubTeam, o.owners.OwnersRepo),
fmt.Sprintf("Sync Github Team %s with %s owners", o.GitHubTeam, o.owners.RepositoryName),
fmt.Sprintf(`This PR synchronizes the Github Team %s with the leaf approvers declared in %s repository's [OWNERS](%s) file.
%s
`, o.GitHubTeam, o.owners.OwnersRepo, ownersDoc, syncerSignature),
`, o.GitHubTeam, o.owners.RepositoryName, ownersDoc, syncerSignature),
fmt.Sprintf("%s:%s", o.github.Username, ref),
o.orgs.ConfigBaseRef,
false,
)
if err != nil {
return errors.Wrap(err, "error creating GitHub Pull Request")
return errors.Wrap(err, "error creating github pull request")
}

output.Print(
Expand All @@ -253,20 +254,51 @@ Signed-off-by: %s <%s>
func (o *options) loadOwnersFromGithub(githubClient github.Client) (repoowners.RepoOwner, error) {
gitClientFactory, err := o.github.GetGitClientFactory()
if err != nil {
return nil, errors.Wrap(err, "error building git client gitClientFactory")
return nil, errors.Wrap(err, "error building git client gitclientfactory")
}

ownersClient := o.owners.NewClient(githubClient, gitClientFactory)
ownersClient := owners.NewClient(githubClient, gitClientFactory)

// Load Owners hierarchy from specified repository.
owners, err := ownersClient.LoadRepoOwners(o.GitHubOrg, o.owners.OwnersRepo, o.owners.OwnersGitRef)
owners, err := ownersClient.LoadRepoOwners(o.GitHubOrg, o.owners.RepositoryName, o.owners.GitRef)
if err != nil {
return nil, errors.Wrap(err, "error loading owners from repository")
}

return owners, nil
}

func (o *options) loadPeopleFromOwners(owners repoowners.RepoOwner) []string {
var people []string

switch {
// Limiting the scope of the roles.
case o.owners.ConfigPath != "":
if o.owners.ApproversOnly {
// Approvers of the subpart of the repository.
people = maps.Keys(owners.Approvers(o.owners.ConfigPath).Set())
} else if o.owners.ReviewersOnly {
// Reviewers of the subpart of the repository.
people = maps.Keys(owners.Reviewers(o.owners.ConfigPath).Set())
} else {
// Both approvers and reviewers of the subpart of the repository.
people = maps.Keys(owners.Approvers(o.owners.ConfigPath).
Union(owners.Reviewers(o.owners.ConfigPath)).Set())
}
// Approvers of the whole repository.
case o.owners.ApproversOnly:
people = maps.Keys(owners.AllApprovers())
// Reviewers of the whole repository.
case o.owners.ReviewersOnly:
people = maps.Keys(owners.AllReviewers())
// Both approvers and reviewers of the whole repository.
default:
people = maps.Keys(owners.AllOwners())
}

return people
}

func (o *options) flushConfig(config *peribolos.FullConfig, configPath string) error {
b, err := yaml.Marshal(config)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/sync/local/sync_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package local

import (
"fmt"
"github.com/maxgio92/peribolos-syncer/internal/sync"
"os"

"github.com/pkg/errors"
Expand All @@ -27,6 +26,7 @@ import (
"sigs.k8s.io/yaml"

"github.com/maxgio92/peribolos-syncer/internal/output"
"github.com/maxgio92/peribolos-syncer/internal/sync"
orgs "github.com/maxgio92/peribolos-syncer/pkg/peribolos"
)

Expand Down
4 changes: 3 additions & 1 deletion docs/peribolos-syncer_sync_github.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ peribolos-syncer sync github --org=acme --team=app-maintainers
### Options

```
--approvers-only Whether to load only the approvers from the Owners config
--dry-run Dry run for testing. Uses API tokens but does not mutate.
--git-author-email string The Git author email with which write commits for the update of the Peribolos config
--git-author-name string The Git author name with which write commits for the update of the Peribolos config
Expand All @@ -48,12 +49,13 @@ peribolos-syncer sync github --org=acme --team=app-maintainers
--gpg-public-key string The path to the public GPG key for signing git commits
-h, --help help for github
--org string The name of the GitHub organization to update configuration for
--owners-config-path string The path to the Owners config file from the root of the Git repository. When specified, they are considered people for which the roles are applied from the root until the specified path.
-r, --owners-git-ref string The base Git reference at which parse the OWNERS hierarchy (default "master")
-o, --owners-path string The path to the OWNERS file from the root of the Git repository. Ignored with sync-github.
--owners-repository string The name of the github repository from which parse OWNERS file
--peribolos-config-git-ref string The base Git reference at which pull the peribolos config repository (default "master")
-c, --peribolos-config-path string The path to the peribolos organization config file from the root of the Git repository (default "org.yaml")
--peribolos-config-repository string The name of the github repository that contains the peribolos organization config file
--reviewers-only Whether to load only the reviewers from the Owners config
--team string The name of the GitHub team to update configuration for
```

Expand Down
22 changes: 12 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ require (
github.com/go-git/go-billy/v5 v5.3.1
github.com/go-git/go-git/v5 v5.4.2
github.com/google/uuid v1.3.0
github.com/onsi/ginkgo/v2 v2.1.4
github.com/onsi/gomega v1.19.0
github.com/onsi/ginkgo/v2 v2.9.2
github.com/onsi/gomega v1.27.4
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0
k8s.io/test-infra v0.0.0-20230311160640-363dd0f9d845
k8s.io/test-infra v0.0.0-20230504092043-c36e3c5f46b4
sigs.k8s.io/yaml v1.3.0
)

Expand Down Expand Up @@ -62,15 +62,16 @@ require (
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/gomodule/redigo v1.8.5 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-containerregistry v0.8.1-0.20220216220642-00c59d91847c // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.1-0.20210504230335-f78f29fc09ea // indirect
Expand Down Expand Up @@ -122,13 +123,14 @@ require (
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
gocloud.dev v0.19.0 // indirect
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
golang.org/x/tools v0.7.0 // indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/api v0.83.0 // indirect
Expand Down
Loading

0 comments on commit c718728

Please sign in to comment.