-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for GitHub Nested Teams 🐣 #8486
Conversation
ecaeb72
to
26f555f
Compare
prow/config/org/org.go
Outdated
Privacy *Privacy `json:"privacy,omitempty"` | ||
Description *string `json:"description,omitempty"` | ||
Privacy *Privacy `json:"privacy,omitempty"` | ||
ParentTeamID *int `json:"parent_team_id,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this and add a Children map[string]Team
field in Team
(or maybe Teams)
We would want the config to be something like:
teams:
sig-foo:
description: foo enthusiasts
teams:
sig-foo-leads:
members:
- george
sig-foo-pr-reviews:
members:
- jane
prow/github/types.go
Outdated
@@ -579,6 +579,16 @@ type Team struct { | |||
Name string `json:"name,omitempty"` | |||
Description string `json:"description,omitempty"` | |||
Privacy string `json:"privacy,omitempty"` | |||
Parent *Team `json:"parent,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ParentTeamID here, get rid of the unnecessary NewTeam
struct
prow/cmd/peribolos/main.go
Outdated
@@ -651,7 +657,7 @@ func configureOrg(opt options, client *github.Client, orgName string, orgConfig | |||
} | |||
|
|||
type editTeamClient interface { | |||
EditTeam(team github.Team) (*github.Team, error) | |||
EditTeam(team github.NewTeam) (*github.Team, error) | |||
} | |||
|
|||
// configureTeam patches the team name/description/privacy when values differ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change configureTeam()
to receive the parent int
and do something like:
func configureTeam(client editTeamClient, orgName, teamName string, team org.Team, gt github.Team, parent int) error {
// ...
if parent > 0 && gt.ParentID != parent {
gt.ParentID = parent
patch = true
}
// ...
}
Then in configureOrg()
the for name, team := range orgConfig.Teams { ... }
probably needs to be in its own recursive function:
func configureOrg(...) {
// ...
for name, team := range orgConfig.Teams {
// move what's currently here into the configureTeamAndMembers()
configureTeamAndMembers(client, githubTeams, name, team, 0) // top level teams have no parent
}
...
}
func configureTeamAndMembers(client, githubTeams map[string]github.Team, name string, team org.Team, parent int) error {
gt, ok := githubTeams[name]
err := configureTeam(client, orgName, name, team, parent)
err := configureTeamMembers(client, gt.ID, team)
for childName, childTeam := range team.Teams {
err := configureTeamAndMembers(client, githubTeams, childName, childTeam, gt.ID)
}
}
prow/cmd/peribolos/main.go
Outdated
@@ -231,6 +231,9 @@ func dumpOrgConfig(client dumpClient, orgName string) (*org.Config, error) { | |||
Maintainers: []string{}, | |||
Members: []string{}, | |||
} | |||
if t.Parent.ID != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should construct the recursive tree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a skeleton for how we can convert the github response into the tree we want for --dump
prow/cmd/peribolos/main.go
Outdated
} | ||
for _, m := range teamMembers { | ||
nt.Members = append(nt.Members, m.Login) | ||
out.Teams = make(map[string]org.Team) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the general goal here is:
a) Convert github.Team metadata into org.Team metadata
b) Figure out what children a given parent has
c) Create the tree of children, starting at ancestors.
So then we wind up with something like this:
names := map[int]string{} // what's the name of a team?
idMap := map[int]org.Team{} // metadata for a team
children := map[int][]int // what children does it have
var tops []int // what are the top-level teams
// first create all the org.Team items
for _, t := range teams {
nt := org.Team{
TeamMetadata: org.TeamMetadata{
Description: t.Description
},
Maintainer: client.ListTeamMembers(t.ID)
}
names[t.ID] = t.Name
idMap[t.ID] = nt
if t.ParentID == 0 { // top level team
tops = append(tops, t.ID)
} else { // add this id to the list of the parent's children
children[t.ParentID] = append(children[t.ParentID], t.ID)
}
}
makeChild := func(id int) org.Team {
t := idMap[id]
for _, cid := range children[id] {
child := makeChild(cid)
t.Children = append(t.Children, child)
}
return t
}
for _, id := range tops {
out.Teams[names[id]] = makeChild(id)
}
1941437
to
f3330aa
Compare
@fejta I think this is ready for another review. Got the dump working (thanks for the help!). Example from kubernetes-sigs:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🍾 very cool
A couple comments
prow/github/types.go
Outdated
Name string `json:"name,omitempty"` | ||
Description string `json:"description,omitempty"` | ||
Privacy string `json:"privacy,omitempty"` | ||
Parent *Team `json:"parent,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe note with a comment that this is only relevant for responses
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
prow/cmd/peribolos/main_test.go
Outdated
@@ -1077,7 +1077,7 @@ func TestConfigureTeam(t *testing.T) { | |||
for _, tc := range cases { | |||
t.Run(tc.name, func(t *testing.T) { | |||
fc := makeFakeTeamClient(tc.github) | |||
err := configureTeam(fc, fakeOrg, tc.teamName, tc.config, tc.github) | |||
err := configureTeam(fc, fakeOrg, tc.teamName, tc.config, tc.github, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will you s/0/tc.parentID
and ensure cover this in "do not patch team when values are the same" and have a "patch team when parent changes"
prow/cmd/peribolos/main.go
Outdated
@@ -675,6 +721,11 @@ func configureTeam(client editTeamClient, orgName, teamName string, team org.Tea | |||
} else { | |||
gt.Privacy = "" | |||
} | |||
if parent > 0 && gt.ParentTeamID != &parent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I make a child team into a top-level team by later setting its parentID to 0? I think so, in which case we probably don't need the parent > 0
check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no.. you actually need to send parent_team_id: null
for that to work. removed the omitempty so it will handle this case.
@fejta Addressed comments, but having some issues with the tests.. would you mind having a look at 9a6de59 ? there might be something dumb and obvious I'm missing.. both the test cases you call out are failing:
|
@@ -655,7 +701,7 @@ type editTeamClient interface { | |||
} | |||
|
|||
// configureTeam patches the team name/description/privacy when values differ | |||
func configureTeam(client editTeamClient, orgName, teamName string, team org.Team, gt github.Team) error { | |||
func configureTeam(client editTeamClient, orgName, teamName string, team org.Team, gt github.Team, parent *int) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand the motivation behind / value of changing this to parent *int
instead of int
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0
is technically a valid parent team ID. We need to be able to tell the difference between 0
and nil
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it, thanks! Can you include a unit test for removing the parent from a team then?
prow/cmd/peribolos/main_test.go
Outdated
@@ -698,6 +698,13 @@ func (c *fakeTeamClient) EditTeam(team github.Team) (*github.Team, error) { | |||
if team.Privacy != "" { | |||
t.Privacy = team.Privacy | |||
} | |||
if team.ParentTeamID != nil { | |||
team.Parent = &github.Team{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong lvalue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused.. I don't think it is. The goal here in the fake client is to take ParentTeamID, and set the Parent struct to contain a fake team with that matching ID.
EDIT: I get it now.
cases := []struct { | ||
name string | ||
err bool | ||
teamName string | ||
parent *int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where do you use this value?
config: org.Team{}, | ||
github: github.Team{ | ||
ID: 3, | ||
Name: whatev, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make sure the parent ID is the only bad value.
By making config.Name != github.Name
also differ it is no longer clear that ParentTeamID
change causes an update (might just be luck due to the name diff).
prow/cmd/peribolos/main_test.go
Outdated
Name: whatev, | ||
Parent: &github.Team{ | ||
ID: 4, | ||
Name: "sup", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically Name
is unnecessary here. Consider removing for clarity
@fejta oooookay. I think I got this figured out, and the tests working. PTAL, and I'll squash after.. thanks again for the pointers! :) |
commit includes an emoji, auto |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
/hold
Squashified! |
/test pull-test-infra-bazel-canary |
Sorry for the noise, this is the failure I'm looking for, after
#8525 hopefully we'll have the
fix confirmed.
…On Sat, Jun 30, 2018 at 11:34 AM k8s-ci-robot ***@***.***> wrote:
@cblecker <https://github.com/cblecker>: The following test *failed*, say
/retest to rerun them all:
Test name Commit Details Rerun command
pull-test-infra-bazel-canary 7f86b7a
<7f86b7a>
link
<https://k8s-gubernator.appspot.com/build/kubernetes-jenkins/pr-logs/pull/test-infra/8486/pull-test-infra-bazel-canary/197/> /test
pull-test-infra-bazel-canary
Full PR test history
<https://k8s-gubernator.appspot.com/pr/test-infra/8486>. Your PR dashboard
<https://k8s-gubernator.appspot.com/pr/cblecker>. Please help us cut down
on flakes by linking to
<https://git.k8s.io/community/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests>
an open issue
<https://github.com/kubernetes/test-infra/issues?q=is:issue+is:open> when
you hit one in your PR.
Instructions for interacting with me using PR comments are available here
<https://git.k8s.io/community/contributors/guide/pull-requests.md>. If
you have questions or suggestions related to my behavior, please file an
issue against the kubernetes/test-infra
<https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:>
repository. I understand the commands that are listed here
<https://go.k8s.io/bot-commands>.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#8486 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA4Bqx3OSeCW6Qy4QSqfM3e1DH0Uh3_Yks5uB8SlgaJpZM4U6cQB>
.
|
return t | ||
} | ||
|
||
out.Teams = make(map[string]org.Team, len(tops)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last change.. moved this line down here from L222
/test pull-test-infra-bazel-canary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: cblecker, fejta The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/hold cancel |
/retest |
Add support for Github Nested Teams to peribolos.
https://blog.github.com/2017-06-13-nested-teams-add-depth-to-your-team-structure/
example config: