|
|
@@ -1,145 +0,0 @@
|
|
|
-"""Updates the contributors-with-label-access team.
|
|
|
-
|
|
|
-This team exists because we need a team to manage triage access to repos;
|
|
|
-GitHub doesn't allow the org to be set to triage access, only read/write. It
|
|
|
-will be updated to include all members of the carbon-language organization.
|
|
|
-"""
|
|
|
-
|
|
|
-__copyright__ = """
|
|
|
-Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
|
-Exceptions. See /LICENSE for license information.
|
|
|
-SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
-"""
|
|
|
-
|
|
|
-import argparse
|
|
|
-from typing import List, Optional, Set
|
|
|
-
|
|
|
-# https://github.com/PyGithub/PyGithub
|
|
|
-# GraphQL is preferred, but falling back to pygithub for unsupported mutations.
|
|
|
-import github
|
|
|
-
|
|
|
-from github_tools import github_helpers
|
|
|
-
|
|
|
-# The organization to mirror members from.
|
|
|
-_ORG = "carbon-language"
|
|
|
-
|
|
|
-# The team to mirror to.
|
|
|
-_TEAM = "contributors"
|
|
|
-
|
|
|
-# Accounts in the org to skip mirroring.
|
|
|
-_IGNORE_ACCOUNTS = ("CarbonLangInfra", "google-admin", "googlebot")
|
|
|
-
|
|
|
-# Queries organization members.
|
|
|
-_ORG_MEMBER_QUERY = """
|
|
|
-query {
|
|
|
- organization(login: "%s") {
|
|
|
- membersWithRole(first: 100%%(cursor)s) {
|
|
|
- nodes {
|
|
|
- login
|
|
|
- }
|
|
|
- %%(pagination)s
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-"""
|
|
|
-
|
|
|
-# The path for nodes in _ORG_MEMBER_QUERY.
|
|
|
-_ORG_MEMBER_PATH = ("organization", "membersWithRole")
|
|
|
-
|
|
|
-# Queries team members.
|
|
|
-_TEAM_MEMBER_QUERY = """
|
|
|
-query {
|
|
|
- organization(login: "%s") {
|
|
|
- team(slug: "%s") {
|
|
|
- members(first: 100%%(cursor)s) {
|
|
|
- nodes {
|
|
|
- login
|
|
|
- }
|
|
|
- %%(pagination)s
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-"""
|
|
|
-
|
|
|
-# The path for nodes in _TEAM_MEMBER_QUERY.
|
|
|
-_TEAM_MEMBER_PATH = ("organization", "team", "members")
|
|
|
-
|
|
|
-
|
|
|
-def _parse_args(args: Optional[List[str]] = None) -> argparse.Namespace:
|
|
|
- """Parses command-line arguments and flags."""
|
|
|
- parser = argparse.ArgumentParser(description=__doc__)
|
|
|
- github_helpers.add_access_token_arg(parser, "admin:org, repo")
|
|
|
- return parser.parse_args(args=args)
|
|
|
-
|
|
|
-
|
|
|
-def _load_org_members(client: github_helpers.Client) -> Set[str]:
|
|
|
- """Loads org members."""
|
|
|
- print("Loading %s..." % _ORG)
|
|
|
- org_members = set()
|
|
|
- ignored = set()
|
|
|
- for node in client.execute_and_paginate(
|
|
|
- _ORG_MEMBER_QUERY % _ORG, _ORG_MEMBER_PATH
|
|
|
- ):
|
|
|
- login = node["login"]
|
|
|
- if login not in _IGNORE_ACCOUNTS:
|
|
|
- org_members.add(login)
|
|
|
- else:
|
|
|
- ignored.add(login)
|
|
|
- print(
|
|
|
- "%s has %d non-ignored members, and %d ignored."
|
|
|
- % (_ORG, len(org_members), len(ignored))
|
|
|
- )
|
|
|
- unignored = set(_IGNORE_ACCOUNTS) - ignored
|
|
|
- assert not unignored, "Missing ignored accounts: %s" % unignored
|
|
|
- return org_members
|
|
|
-
|
|
|
-
|
|
|
-def _load_team_members(client: github_helpers.Client) -> Set[str]:
|
|
|
- """Load team members."""
|
|
|
- print("Loading %s..." % _TEAM)
|
|
|
- team_members = set()
|
|
|
- for node in client.execute_and_paginate(
|
|
|
- _TEAM_MEMBER_QUERY % (_ORG, _TEAM), _TEAM_MEMBER_PATH
|
|
|
- ):
|
|
|
- team_members.add(node["login"])
|
|
|
- print("%s has %d members." % (_ORG, len(team_members)))
|
|
|
- return team_members
|
|
|
-
|
|
|
-
|
|
|
-def _update_team(
|
|
|
- gh: github.Github, org_members: Set[str], team_members: Set[str]
|
|
|
-) -> None:
|
|
|
- """Updates the team if needed.
|
|
|
-
|
|
|
- This switches to pygithub because GraphQL lacks equivalent mutation support.
|
|
|
- """
|
|
|
- gh_team = gh.get_organization(_ORG).get_team_by_slug(_TEAM)
|
|
|
- add_members = org_members - team_members
|
|
|
- if add_members:
|
|
|
- print("Adding members: %s" % ", ".join(add_members))
|
|
|
- for member in add_members:
|
|
|
- gh_team.add_membership(gh.get_user(member))
|
|
|
-
|
|
|
- remove_members = team_members - org_members
|
|
|
- if remove_members:
|
|
|
- print("Removing members: %s" % ", ".join(remove_members))
|
|
|
- for member in remove_members:
|
|
|
- gh_team.remove_membership(gh.get_user(member))
|
|
|
-
|
|
|
-
|
|
|
-def main() -> None:
|
|
|
- parsed_args = _parse_args()
|
|
|
- print("Connecting...")
|
|
|
- client = github_helpers.Client(parsed_args)
|
|
|
-
|
|
|
- org_members = _load_org_members(client)
|
|
|
- team_members = _load_team_members(client)
|
|
|
- if org_members != team_members:
|
|
|
- gh = github.Github(parsed_args.access_token)
|
|
|
- _update_team(gh, org_members, team_members)
|
|
|
- print("Done!")
|
|
|
-
|
|
|
-
|
|
|
-if __name__ == "__main__":
|
|
|
- main()
|