diff --git a/README.md b/README.md index d925842..a7dd150 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,13 @@ # Team manager -Team manager is a utility that allows an organization owner to add or remove +Team manager is a utility that allows an organization owner to: +- add or remove people from existing teams and / or assign people for [GitHub team review -assignments](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/managing-code-review-assignment-for-your-team). +assignments](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/managing-code-review-assignment-for-your-team); +- configure repository permissions for teams and individual users; +- keep track of all "outside collaborators" and the reason why they are outside + collaborators; +- check if all teams have enough reviewers; ## Features @@ -11,14 +16,16 @@ assignments](https://docs.github.com/en/github/setting-up-and-managing-organizat - [X] Sync local configuration file into GitHub. - [X] Add and / or remove new members to / from teams. - [X] Exclude team members from code review assignments. +- [x] Create or delete teams that are added or removed from the local + configuration file. +- [x] Sync team and user permissions of repositories. +- [x] Check Status of teams. Useful to know if teams have enough reviewers. - [X] GitHub action (see example below) ## Missing features - [ ] Retrieve excluded team members from the code review assignments (not provided by GitHub API). -- [ ] Create or delete teams that are added or removed from the local - configuration file. # Build @@ -28,7 +35,7 @@ make team-manager # Usage -1. Generate a GitHub token that has `admin:org`. [direct link](https://github.com/settings/tokens/new) +1. Generate a GitHub token that has `admin:org` and `public_repo`. [direct link](https://github.com/settings/tokens/new?description=Team%20Management&scopes=write:org,public_repo) 2. Generate configuration for your organization @@ -44,8 +51,18 @@ Creating configuration file "cilium-team-assignments.yaml"... ```yaml organization: cilium -slackWorkspace: cilium.slack.com -# List of members that belong to the organization, ordered by GitHub login (username). +repositories: + # Repository name + cilium: + # User-specific permissions. Always prefixed with 'USER'. + # Valid options: 'USER-ADMIN', 'USER-MAINTAIN', 'USER-WRITE', 'USER-TRIAGE', 'USER-READ' + USER-READ: + - ciliumbot + # Team-specific permissions. + # Valid options: 'ADMIN', 'MAINTAIN', 'WRITE', 'TRIAGE', 'READ' + WRITE: + - bpf + - sig-policy members: aanm: # User ID, retrieved from GitHub @@ -60,35 +77,62 @@ members: joestringer: id: MDQ6VXNlcjEyNDMzMzY= name: Joe Stringer -# List of teams that belong to the organization, ordered by team names. +# The list of 'outsideCollaborators' is automatically derived from the list of users that don't +# belong to the organization but have access to at least one of the repositories +# of the organization. +outsideCollaborators: + ciliumbot: + reason: "Only has access to some repositories" +# List of teams that belong to the organization. teams: - bpf: + # Team Name + Cilium Teams: # team ID, retrieved from GitHub - id: MDQ6VGVhbTI1MTk3Nzk= - # List of members' logins that belong to this team. - members: - - aanm - - borkmann - - joestringer - # codeReviewAssignment - codeReviewAssignment: - # algorithm, currently can be LOAD_BALANCE or ROUND_ROBIN. - algorithm: LOAD_BALANCE - # set 'true' if codeReviewAssignment should be enabled. - enabled: true - # Notify the entire team of the PR if it is delegated. - notifyTeam: false - # List of members that should be excluded from receiving reviews, and an - # optional reason. - excludedMembers: - # GitHub login name (username). - - login: aanm - reason: Want to be part of team 'bpf' but will not be assigned to leave - reviews. - # The number of team members to assign. - teamMemberCount: 1 + id: T_kwDOAUFEZs4Ah5D3 + # team restID, retrieved from GitHub + restID: 8884471 + # Team's description + description: Teams and sigs used for Cilium projects + # Team's privacy settings. Valid values: VISIBLE|SECRET + privacy: VISIBLE + # Teams that are children of this parent team + children: + # Team Name + ebpf: + # team ID, retrieved from GitHub + id: MDQ6VGVhbTQ5MjY2ODE= + # team restID, retrieved from GitHub + restID: 4926681 + # Team's description + description: All code related with ebpf. + # List of members' logins that belong to this team. + members: + - aanm + - borkmann + - joestringer + codeReviewAssignment: + # algorithm, currently can be LOAD_BALANCE or ROUND_ROBIN. + algorithm: LOAD_BALANCE + # set 'true' if codeReviewAssignment should be enabled. + enabled: true + # Notify the entire team of the PR if it is delegated. + notifyTeam: false + # List of members that should be excluded from receiving reviews, and + # an optional reason. + excludedMembers: + # GitHub login name (username). + - login: aanm + reason: Want to be part of team 'bpf' but will not be assigned to leave + reviews. + # The number of team members to assign. + teamMemberCount: 1 + # Team's privacy settings. Valid values: VISIBLE|SECRET + privacy: VISIBLE + # Team Name policy: id: MDQ6VGVhbTI1MTk3ODY= + restID: 8884472 + description: All control plane code related with Policy members: - aanm - joestringer @@ -97,6 +141,7 @@ teams: enabled: true notifyTeam: true teamMemberCount: 1 + privacy: SECRET # List of members that should be excluded from review assignments for the teams # that they belong. This list can exist for numerous reasons, person is # currently PTO or busy with other work. @@ -107,7 +152,7 @@ excludeCodeReviewAssignmentFromAllTeams: 4. Once the changes stored in a local configuration file, run `./team-manager push --org cilium`: ```bash -$ ./team-manager push --org cilium +$ ./team-manager push --config-filename ./cilium-team-assignments.yaml Local config out of sync with upstream: Unified diff: --- local +++ remote @@ -136,8 +181,30 @@ Excluding members from team: bpf Excluding members from team: policy ``` +# Repository and members sync + +Starting with v1.0.0, team-manager has the ability to also sync repository and +members permissions. Before changing the file locally to push new changes, +it is important to always perform a 'sync': +```bash +$ ./team-manager sync --config-filename ./team-assignments.yaml +``` + +Then, after modifying the file on `team-assignments.yaml`, push the changes: + +```bash +$ ./team-manager push --config-filename ./team-assignments.yaml +``` + # GitHub action +On a large GitHub organization, it might be difficult to control who can create +repositories. Thus, when running team manager with a GitHub action, it should +run with `--repositories=false` and `--members=false` otherwise the GitHub +action might override repository permissions that were set from the web-ui +and remove or add members to the organization that were previously added or +removed from the web-ui. + ```yaml name: Team management on: @@ -151,12 +218,44 @@ jobs: name: Team sync runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v1 - - uses: docker://quay.io/cilium/team-manager:v0.0.1 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: docker://quay.io/cilium/team-manager:v1.0.0 name: Sync team with: entrypoint: team-manager - args: push --force --config-filename ./team-assignments.yaml + # With --repositories=false --members=false, it will have the same + # behavior as <= v0.0.8. + args: push --force --repositories=false --members=false --config-filename ./team-assignments.yaml env: GITHUB_TOKEN: ${{ secrets.ADMIN_ORG_TOKEN }} -``` \ No newline at end of file +``` + +# Check number of reviewers + +To disable code review assignments, the GitHub user can either set its status as +'busy' or the team maintainer can exclude them from the list of reviewers. + +Since the team maintainer can't control the status of the user, it is important +to retrieve the list of teams that don't have enough reviewers, by checking +which users have their status as 'busy' or the ones that are excluded from +reviews. + +```bash +$ ./team-manager status --config-filename ./cilium-team-assignments.yaml +Checking status of "aanm" +Checking status of "joestringer" +Checking status of "borkmann" +Team "bpf" with 3 members doesn't have enough reviewers: + - aanm - excluded + - joestringer - busy + - borkmann - ok +``` + +# Upgrade from <=0.0.8 to 1.0.0 + +1. Use 'sync' to sync the upstream configuration with the local file. It will + fetch the information from GitHub and merge it with the local file. + +```bash +$ ./team-manager sync --config-filename ./team-assignments.yaml +``` diff --git a/cmd/teams.go b/cmd/teams.go index a462782..9ffd355 100644 --- a/cmd/teams.go +++ b/cmd/teams.go @@ -7,7 +7,7 @@ import ( "context" "fmt" - gh "github.com/google/go-github/v33/github" + gh "github.com/google/go-github/v57/github" "github.com/spf13/cobra" "github.com/cilium/team-manager/pkg/config" diff --git a/cmd/users.go b/cmd/users.go index 3a8374f..ecf09a9 100644 --- a/cmd/users.go +++ b/cmd/users.go @@ -8,7 +8,7 @@ import ( "fmt" "strings" - gh "github.com/google/go-github/v33/github" + gh "github.com/google/go-github/v57/github" "github.com/spf13/cobra" "github.com/cilium/team-manager/pkg/config" diff --git a/pkg/github/client.go b/pkg/github/client.go index 715a735..98acdab 100644 --- a/pkg/github/client.go +++ b/pkg/github/client.go @@ -19,7 +19,7 @@ import ( "fmt" "os" - gh "github.com/google/go-github/v33/github" + gh "github.com/google/go-github/v57/github" "github.com/shurcooL/githubv4" "golang.org/x/oauth2" ) diff --git a/pkg/team/manager.go b/pkg/team/manager.go index 21859c6..d1098f3 100644 --- a/pkg/team/manager.go +++ b/pkg/team/manager.go @@ -20,7 +20,7 @@ import ( "sort" "strings" - gh "github.com/google/go-github/v33/github" + gh "github.com/google/go-github/v57/github" "github.com/schollz/progressbar/v3" "github.com/shurcooL/githubv4" "github.com/shurcooL/graphql" diff --git a/pkg/team/push.go b/pkg/team/push.go index 1151ce2..1dcf64c 100644 --- a/pkg/team/push.go +++ b/pkg/team/push.go @@ -26,7 +26,7 @@ import ( "github.com/cilium/team-manager/pkg/github" "github.com/cilium/team-manager/pkg/slices" "github.com/cilium/team-manager/pkg/terminal" - gh "github.com/google/go-github/v33/github" + gh "github.com/google/go-github/v57/github" "github.com/shurcooL/githubv4" ) diff --git a/team-assignments.yaml b/team-assignments.yaml index d201f27..9c81467 100644 --- a/team-assignments.yaml +++ b/team-assignments.yaml @@ -1,6 +1,16 @@ organization: cilium -slackWorkspace: cilium.slack.com -# List of members that belong to the organization, ordered by GitHub login (username). +repositories: + # Repository name + cilium: + # User-specific permissions. Always prefixed with 'USER'. + # Valid options: 'USER-ADMIN', 'USER-MAINTAIN', 'USER-WRITE', 'USER-TRIAGE', 'USER-READ' + USER-READ: + - ciliumbot + # Team-specific permissions. + # Valid options: 'ADMIN', 'MAINTAIN', 'WRITE', 'TRIAGE', 'READ' + WRITE: + - bpf + - sig-policy members: aanm: # User ID, retrieved from GitHub @@ -15,35 +25,62 @@ members: joestringer: id: MDQ6VXNlcjEyNDMzMzY= name: Joe Stringer -# List of teams that belong to the organization, ordered by team names. +# The list of 'outsideCollaborators' is automatically derived from the list of users that don't +# belong to the organization but have access to at least one of the repositories +# of the organization. +outsideCollaborators: + ciliumbot: + reason: "Only has access to some repositories" +# List of teams that belong to the organization. teams: - bpf: + # Team Name + Cilium Teams: # team ID, retrieved from GitHub - id: MDQ6VGVhbTI1MTk3Nzk= - # List of members' logins that belong to this team. - members: - - aanm - - borkmann - - joestringer - # codeReviewAssignment - codeReviewAssignment: - # algorithm, currently can be LOAD_BALANCE or ROUND_ROBIN. - algorithm: LOAD_BALANCE - # set 'true' if codeReviewAssignment should be enabled. - enabled: true - # Notify the entire team of the PR if it is delegated. - notifyTeam: false - # List of members that should be excluded from receiving reviews, and an - # optional reason. - excludedMembers: - # GitHub login name (username). - - login: aanm - reason: Want to be part of team 'bpf' but will not be assigned to leave - reviews. - # The number of team members to assign. - teamMemberCount: 1 + id: T_kwDOAUFEZs4Ah5D3 + # team restID, retrieved from GitHub + restID: 8884471 + # Team's description + description: Teams and sigs used for Cilium projects + # Team's privacy settings. Valid values: VISIBLE|SECRET + privacy: VISIBLE + # Teams that are children of this parent team + children: + # Team Name + ebpf: + # team ID, retrieved from GitHub + id: MDQ6VGVhbTQ5MjY2ODE= + # team restID, retrieved from GitHub + restID: 4926681 + # Team's description + description: All code related with ebpf. + # List of members' logins that belong to this team. + members: + - aanm + - borkmann + - joestringer + codeReviewAssignment: + # algorithm, currently can be LOAD_BALANCE or ROUND_ROBIN. + algorithm: LOAD_BALANCE + # set 'true' if codeReviewAssignment should be enabled. + enabled: true + # Notify the entire team of the PR if it is delegated. + notifyTeam: false + # List of members that should be excluded from receiving reviews, and + # an optional reason. + excludedMembers: + # GitHub login name (username). + - login: aanm + reason: Want to be part of team 'bpf' but will not be assigned to leave + reviews. + # The number of team members to assign. + teamMemberCount: 1 + # Team's privacy settings. Valid values: VISIBLE|SECRET + privacy: VISIBLE + # Team Name policy: id: MDQ6VGVhbTI1MTk3ODY= + restID: 8884472 + description: All control plane code related with Policy members: - aanm - joestringer @@ -52,6 +89,7 @@ teams: enabled: true notifyTeam: true teamMemberCount: 1 + privacy: SECRET # List of members that should be excluded from review assignments for the teams # that they belong. This list can exist for numerous reasons, person is # currently PTO or busy with other work. diff --git a/team-manager-github-action.yaml b/team-manager-github-action.yaml index 2d21306..1a9419c 100644 --- a/team-manager-github-action.yaml +++ b/team-manager-github-action.yaml @@ -8,13 +8,15 @@ jobs: sync: # if: github.repository == '/' name: Team sync - runs-on: ubuntu-20.04 + runs-on: latest steps: - - uses: actions/checkout@v1 - - uses: docker://quay.io/cilium/team-manager:v0.0.8 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: docker://quay.io/cilium/team-manager:v1.0.0 name: Sync team with: entrypoint: team-manager - args: --force --config-filename ./team-assignments.yaml + # With --repositories=false --members=false, it will have the same + # behavior as <= v0.0.8. + args: push --force --repositories=false --members=false --config-filename ./team-assignments.yaml env: - GITHUB_TOKEN: ${{ secrets.ADMIN_ORG_TOKEN }} + GITHUB_TOKEN: ${{ secrets.ADMIN_ORG_TOKEN }} \ No newline at end of file